home *** CD-ROM | disk | FTP | other *** search
/ Creating Your Own America Online Web Pages / Creating Your Own America Online Web Pages.iso / TOOLS / TEX2RTF / SOURCES.ZIP / SRC / TEX2ANY.CC < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-23  |  91.3 KB  |  3,299 lines

  1. /*
  2.  * File:     tex2any.cc
  3.  * Purpose:  Conversion utility for LaTeX files
  4.  *
  5.  *                       wxWindows 1.50
  6.  * Copyright (c) 1993 Artificial Intelligence Applications Institute,
  7.  *                   The University of Edinburgh
  8.  *
  9.  *                     Author: Julian Smart
  10.  *                        Date: 7-9-93
  11.  *
  12.  * Permission to use, copy, modify, and distribute this software and its
  13.  * documentation for any purpose is hereby granted without fee, provided
  14.  * that the above copyright notice, author statement and this permission
  15.  * notice appear in all copies of this software and related documentation.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS,
  18.  * IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
  19.  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  20.  *
  21.  * IN NO EVENT SHALL THE ARTIFICIAL INTELLIGENCE APPLICATIONS INSTITUTE OR THE
  22.  * UNIVERSITY OF EDINBURGH BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR
  23.  * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM
  24.  * LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF
  25.  * DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH
  26.  * THE USE OR PERFORMANCE OF THIS SOFTWARE.
  27.  */
  28.  
  29. #include <wx.h>
  30. #include <ctype.h>
  31. #include "tex2any.h"
  32. #include <stdlib.h>
  33. #include <time.h>
  34.  
  35. /*
  36.  * Variables accessible from clients
  37.  *
  38.  */
  39.  
  40. TexChunk *      DocumentTitle = NULL;
  41. TexChunk *      DocumentAuthor = NULL;
  42. TexChunk *      DocumentDate = NULL;
  43.  
  44. // Header/footers/pagestyle
  45. TexChunk *      LeftHeaderEven = NULL;
  46. TexChunk *      LeftFooterEven = NULL;
  47. TexChunk *      CentreHeaderEven = NULL;
  48. TexChunk *      CentreFooterEven = NULL;
  49. TexChunk *      RightHeaderEven = NULL;
  50. TexChunk *      RightFooterEven = NULL;
  51. TexChunk *      LeftHeaderOdd = NULL;
  52. TexChunk *      LeftFooterOdd = NULL;
  53. TexChunk *      CentreHeaderOdd = NULL;
  54. TexChunk *      CentreFooterOdd = NULL;
  55. TexChunk *      RightHeaderOdd = NULL;
  56. TexChunk *      RightFooterOdd = NULL;
  57. char *          PageStyle = copystring("plain");
  58.  
  59. int             DocumentStyle = LATEX_REPORT;
  60. int             MinorDocumentStyle = 0;
  61. wxPathList      TexPathList;
  62. char *          BibliographyStyleString = copystring("plain");
  63. char *          DocumentStyleString = copystring("report");
  64. char *          MinorDocumentStyleString = NULL;
  65. int             ParSkip = 0;
  66. int             ParIndent = 0;
  67.  
  68. int             normalFont = 10;
  69. int             smallFont = 8;
  70. int             tinyFont = 6;
  71. int             largeFont1 = 12;
  72. int             LargeFont2 = 14;
  73. int             LARGEFont3 = 18;
  74. int             hugeFont1 = 20;
  75. int             HugeFont2 = 24;
  76. int             HUGEFont3 = 28;
  77.  
  78. /*
  79.  * USER-ADJUSTABLE SETTINGS
  80.  *
  81.  */
  82.  
  83. // Section font sizes
  84. int             chapterFont =    LARGEFont3;
  85. int             sectionFont =    LargeFont2;
  86. int             subsectionFont = largeFont1;
  87. int             titleFont = LARGEFont3;
  88. int             authorFont = LargeFont2;
  89. int             mirrorMargins = TRUE;
  90. Bool            winHelp = FALSE;  // Output in Windows Help format if TRUE, linear otherwise
  91. Bool            isInteractive = FALSE;
  92. Bool            runTwice = FALSE;
  93. Bool            convertMode = TEX_RTF;
  94. Bool            headerRule = FALSE;
  95. Bool            footerRule = FALSE;
  96. Bool            compatibilityMode = FALSE; // If TRUE, maximum Latex compatibility
  97.                                 // (Quality of RTF generation deteriorate)
  98. Bool            generateHPJ; // Generate WinHelp Help Project file
  99. char            *winHelpTitle = NULL; // Windows Help title
  100. int             defaultTableColumnWidth = 2000;
  101.  
  102. int             labelIndentTab = 18;  // From left indent to item label (points)
  103. int             itemIndentTab = 40;   // From left indent to item (points)
  104.  
  105. Bool            useUpButton = TRUE;
  106. Bool            htmlBrowseButtons = HTML_BUTTONS_TEXT;
  107.  
  108. Bool            useHeadingStyles = TRUE; // Insert \s1, s2 etc.
  109. Bool            useWord = TRUE; // Insert proper Word table of contents, etc etc
  110. Bool            indexSubsections = TRUE; // Index subsections in linear RTF
  111. // Linear RTF method of including bitmaps. Can be "includepicture", "hex"
  112. char            *bitmapMethod = copystring("includepicture");
  113.  
  114. /*
  115.  * International support
  116.  */
  117.  
  118. // Names to help with internationalisation
  119. char *ContentsNameString = copystring("Contents");
  120. char *GlossaryNameString = copystring("Glossary");
  121. char *ReferencesNameString = copystring("References");
  122. char *FiguresNameString = copystring("List of Figures");
  123. char *TablesNameString = copystring("List of Tables");
  124. char *FigureNameString = copystring("Figure");
  125. char *TableNameString = copystring("Table");
  126. char *IndexNameString = copystring("Index");
  127. char *ChapterNameString = copystring("chapter");
  128. char *SectionNameString = copystring("section");
  129. char *SubsectionNameString = copystring("subsection");
  130. char *SubsubsectionNameString = copystring("subsubsection");
  131. char *UpNameString = copystring("Up");
  132.  
  133. /*
  134.  * Section numbering
  135.  *
  136.  */
  137.  
  138. int             chapterNo = 0;
  139. int             sectionNo = 0;
  140. int             subsectionNo = 0;
  141. int             subsubsectionNo = 0;
  142. int             figureNo = 0;
  143. int             tableNo = 0;
  144.  
  145. /*
  146.  * Other variables
  147.  *
  148.  */
  149.  
  150. FILE *CurrentOutput1 = NULL;
  151. FILE *CurrentOutput2 = NULL;
  152. FILE *Inputs[15];
  153. int LineNumbers[15];
  154. char *FileNames[15];
  155. int CurrentInputIndex = 0;
  156.  
  157. char *TexFileRoot = NULL;
  158. char *TexBibName = NULL;         // Bibliography output file name
  159. char *TexTmpBibName = NULL;      // Temporary bibliography output file name
  160. Bool isSync = FALSE;             // If TRUE, should not yield to other processes.
  161. Bool stopRunning = FALSE;        // If TRUE, should abort.
  162.  
  163. static int currentColumn = 0;
  164. char *currentArgData = NULL;
  165. Bool haveArgData = FALSE; // If TRUE, we're simulating the data.
  166. TexChunk *currentArgument = NULL;
  167. TexChunk *nextChunk = NULL;
  168. Bool isArgOptional = FALSE;
  169. Bool noArgs = 0;
  170.  
  171. TexChunk *TopLevel = NULL;
  172. // wxList MacroDefs(wxKEY_STRING);
  173. wxHashTable MacroDefs(wxKEY_STRING);
  174. wxStringList IgnorableInputFiles; // Ignorable \input files, e.g. psbox.tex
  175. char *BigBuffer = NULL;  // For reading in large chunks of text
  176. TexMacroDef *SoloBlockDef = NULL;
  177. TexMacroDef *VerbatimMacroDef = NULL;
  178.  
  179. #define IncrementLineNumber() LineNumbers[CurrentInputIndex] ++
  180.  
  181. void TexOutput(char *s, Bool ordinaryText)
  182. {
  183.   int len = strlen(s);
  184.  
  185.   // Update current column, but only if we're guaranteed to
  186.   // be ordinary text (not mark-up stuff)
  187.   if (ordinaryText)
  188.     for (int i = 0; i < len; i++)
  189.     {
  190.       if (s[i] == 13 || s[i] == 10)
  191.         currentColumn = 0;
  192.       else
  193.         currentColumn ++;
  194.     }
  195.  
  196.   if (CurrentOutput1)
  197.     fprintf(CurrentOutput1, "%s", s);
  198.   if (CurrentOutput2)
  199.     fprintf(CurrentOutput2, "%s", s);
  200. }
  201.  
  202. /*
  203.  * Try to find a Latex macro, in one of the following forms:
  204.  * (1) \begin{} ... \end{}
  205.  * (2) \macroname{arg1}...{argn}
  206.  * (3) {\bf arg1}
  207.  */
  208.  
  209. void ForbidWarning(TexMacroDef *def)
  210. {
  211.   char buf[100];
  212.   switch (def->forbidden)
  213.   {
  214.     case FORBID_WARN:
  215.     {
  216.       sprintf(buf, "Warning: it is recommended that command %s is not used.", def->name);
  217.       OnInform(buf);
  218.       break;
  219.     }
  220.     case FORBID_ABSOLUTELY:
  221.     {
  222.       sprintf(buf, "Error: command %s cannot be used and will lead to errors.", def->name);
  223.       OnInform(buf);
  224.       break;
  225.     }
  226.     default:
  227.       break;
  228.   }
  229. }
  230.  
  231. TexMacroDef *MatchMacro(char *buffer, int *pos, char **env, Bool *parseToBrace)
  232. {
  233.   *parseToBrace = TRUE;
  234.   int i = (*pos);
  235.   TexMacroDef *def = NULL;
  236.   char macroBuf[40];
  237.  
  238.   // First, try to find begin{thing}
  239.   if (strncmp(buffer+i, "begin{", 6) == 0)
  240.   {
  241.     i += 6;
  242.  
  243.     int j = i;
  244.     while ((isalpha(buffer[j]) || buffer[j] == '*') && ((j - i) < 39))
  245.     {
  246.       macroBuf[j-i] = buffer[j];
  247.       j ++;
  248.     }
  249.     macroBuf[j-i] = 0;
  250.     def = (TexMacroDef *)MacroDefs.Get(macroBuf);
  251.  
  252.     if (def)
  253.     {
  254.       *pos = j + 1;  // BUGBUG Should this be + 1???
  255.       *env = def->name;
  256.       ForbidWarning(def);
  257.       return def;
  258.     }
  259.     else return NULL;
  260.   }
  261.  
  262.   // Failed, so try to find macro from definition list
  263.   int j = i;
  264.  
  265.   // First try getting a one-character macro, but ONLY
  266.   // if these TWO characters are not both alphabetical (could
  267.   // be a longer macro)
  268.   if (!(isalpha(buffer[i]) && isalpha(buffer[i+1])))
  269.   {
  270.     macroBuf[0] = buffer[i];
  271.     macroBuf[1] = 0;
  272.  
  273.     def = (TexMacroDef *)MacroDefs.Get(macroBuf);
  274.     if (def) j ++;
  275.   }
  276.  
  277.   if (!def)
  278.   {
  279.     while ((isalpha(buffer[j]) || buffer[j] == '*') && ((j - i) < 39))
  280.     {
  281.       macroBuf[j-i] = buffer[j];
  282.       j ++;
  283.     }
  284.     macroBuf[j-i] = 0;
  285.     def = (TexMacroDef *)MacroDefs.Get(macroBuf);
  286.   }
  287.     
  288.   if (def)
  289.   {
  290.     i = j;
  291.     
  292.     // We want to check whether this is a space-consuming macro
  293.     // (e.g. {\bf word})
  294.     // No brace, e.g. \input thing.tex instead of \input{thing};
  295.     // or a numeric argument, such as \parindent0pt
  296.     if ((def->no_args > 0) && ((buffer[i] == 32) || (buffer[i] == '=') || (isdigit(buffer[i]))))
  297.     {
  298.       if ((buffer[i] == 32) || (buffer[i] == '='))
  299.         i ++;
  300.  
  301.       *parseToBrace = FALSE;
  302.     }
  303.     *pos = i;
  304.     ForbidWarning(def);
  305.     return def;
  306.   }
  307.   return NULL;
  308. }
  309.  
  310. void EatWhiteSpace(char *buffer, int *pos)
  311. {
  312.   int len = strlen(buffer);
  313.   int j = *pos;
  314.   Bool keepGoing = TRUE;
  315.   Bool moreLines = TRUE;
  316.   while ((j < len) && keepGoing &&
  317.          (buffer[j] == 10 || buffer[j] == 13 || buffer[j] == ' ' || buffer[j] == 9))
  318.   {
  319.     j ++;
  320.     if (j >= len)
  321.     {
  322.       if (moreLines)
  323.       {
  324.         moreLines = read_a_line(buffer);
  325.         len = strlen(buffer);
  326.         j = 0;
  327.       }
  328.       else
  329.         keepGoing = FALSE;
  330.     }
  331.   }
  332.   *pos = j;
  333. }
  334.  
  335. Bool FindEndEnvironment(char *buffer, int *pos, char *env)
  336. {
  337.   int i = (*pos);
  338.  
  339.   // Try to find end{thing}
  340.   if ((strncmp(buffer+i, "end{", 4) == 0) &&
  341.       (strncmp(buffer+i+4, env, strlen(env)) == 0))
  342.   {
  343.     *pos = i + 5 + strlen(env);
  344.     return TRUE;
  345.   }
  346.   else return FALSE;
  347. }
  348.  
  349. Bool readingVerbatim = FALSE;
  350. Bool readInVerbatim = FALSE;  // Within a verbatim, but not nec. verbatiminput
  351.  
  352. Bool read_a_line(char *buf)
  353. {
  354.   if (CurrentInputIndex < 0)
  355.   {
  356.     buf[0] = 0;
  357.     return FALSE;
  358.   }
  359.   
  360.   int ch = -2;
  361.   int i = 0;
  362.   buf[0] = 0;
  363.   while (ch != EOF && ch != 10)
  364.   {
  365.     if (((i == 14) && (strncmp(buf, "\\end{verbatim}", 14) == 0)) ||
  366.          ((i == 16) && (strncmp(buf, "\\end{toocomplex}", 16) == 0)))
  367.       readInVerbatim = FALSE;
  368.  
  369.     ch = getc(Inputs[CurrentInputIndex]);
  370.     if (ch != EOF)
  371.     {
  372.       // Check for 2 consecutive newlines and replace with \par
  373.       if (ch == 10 && !readInVerbatim)
  374.       {
  375.         int ch1 = getc(Inputs[CurrentInputIndex]);
  376.         if ((ch1 == 10) || (ch1 == 13))
  377.         {
  378.           // Eliminate newline (10) following DOS linefeed
  379.           if (ch1 == 13) ch1 = getc(Inputs[CurrentInputIndex]);
  380.           buf[i] = 0;
  381.           IncrementLineNumber();
  382. //          strcat(buf, "\\par\n");
  383. //          i += 6;
  384.           strcat(buf, "\\par");
  385.           i += 5;
  386.         }
  387.         else
  388.         {
  389.           ungetc(ch1, Inputs[CurrentInputIndex]);
  390.           buf[i] = ch;
  391.           i ++;
  392.         }
  393.       }
  394.       else
  395.       {
  396.         buf[i] = ch;
  397.         i ++;
  398.       }
  399.     }
  400.     else
  401.     {
  402.       buf[i] = 0;
  403.       fclose(Inputs[CurrentInputIndex]);
  404.       Inputs[CurrentInputIndex] = NULL;
  405.       if (CurrentInputIndex > 0) ch = ' '; // No real end of file
  406.       CurrentInputIndex --;
  407.       if (readingVerbatim)
  408.       {
  409.         readingVerbatim = FALSE;
  410.         readInVerbatim = FALSE;
  411.         strcat(buf, "\\end{verbatim}\n");
  412.         return FALSE;
  413.       }
  414.     }
  415.     if (ch == 10)
  416.       IncrementLineNumber();
  417.   }
  418.   buf[i] = 0;
  419.  
  420.   // Strip out comment environment
  421.   if (strncmp(buf, "\\begin{comment}", 15) == 0)
  422.   {
  423.     while (strncmp(buf, "\\end{comment}", 13) != 0)
  424.       read_a_line(buf);
  425.     return read_a_line(buf);
  426.   }
  427.   // Read a verbatim input file as if it were a verbatim environment
  428.   else if (strncmp(buf, "\\verbatiminput", 14) == 0)
  429.   {
  430.     int wordLen = 14;
  431.     char *fileName = buf + wordLen + 1;
  432.  
  433.     int j = i - 1;
  434.     buf[j] = 0;
  435.  
  436.     // thing}\par -- eliminate the \par!
  437.     if (strncmp((buf + strlen(buf)-5), "\\par", 4) == 0)
  438.     {
  439.       j -= 5;
  440.       buf[j] = 0;
  441.     }
  442.     
  443.     if (buf[j-1] == '}') buf[j-1] = 0; // Ignore final brace
  444.  
  445.     char *actualFile = TexPathList.FindValidPath(fileName);
  446.     if (!actualFile)
  447.     {
  448.       char errBuf[300];
  449.       strcpy(errBuf, "Could not find file: ");
  450.       strncat(errBuf, fileName, 100);
  451.       OnError(errBuf);
  452.     }
  453.     else
  454.     {
  455.       CurrentInputIndex ++;
  456.       Inputs[CurrentInputIndex] = fopen(actualFile, "r");
  457.       LineNumbers[CurrentInputIndex] = 1;
  458.       if (FileNames[CurrentInputIndex])
  459.         delete[] FileNames[CurrentInputIndex];
  460.       FileNames[CurrentInputIndex] = copystring(actualFile);
  461.  
  462.       if (!Inputs[CurrentInputIndex])
  463.       {
  464.         CurrentInputIndex --;
  465.         OnError("Could not open verbatiminput file.");
  466.       }
  467.       else
  468.       {
  469.         readingVerbatim = TRUE;
  470.         readInVerbatim = TRUE;
  471.         strcpy(buf, "\\begin{verbatim}\n");
  472.         return FALSE;
  473.       }
  474.     }
  475.     return FALSE;
  476.   }
  477.   else if (strncmp(buf, "\\input", 6) == 0 || strncmp(buf, "\\helpinput", 10) == 0 ||
  478.       strncmp(buf, "\\include", 8) == 0)
  479.   {
  480.     int wordLen;
  481.     if (strncmp(buf, "\\input", 6) == 0)
  482.       wordLen = 6;
  483.     else
  484.     if (strncmp(buf, "\\include", 8) == 0)
  485.       wordLen = 8;
  486.     else
  487.       wordLen = 10;
  488.  
  489.     char *fileName = buf + wordLen + 1;
  490.  
  491.     int j = i - 1;
  492.     buf[j] = 0;
  493.  
  494.     // \input{thing}\par -- eliminate the \par!
  495.     if (strncmp((buf + strlen(buf)-5), "\\par", 4) == 0)
  496.     {
  497.       j -= 5;
  498.       buf[j] = 0;
  499.     }
  500.  
  501.     if (buf[j-1] == '}') buf[j-1] = 0; // Ignore final brace
  502.  
  503.     // Ignore some types of input files (e.g. macro definition files)
  504.     char *fileOnly = FileNameFromPath(fileName);
  505.     if (IgnorableInputFiles.Member(fileOnly))
  506.       return read_a_line(buf);
  507.  
  508.     char *actualFile = TexPathList.FindValidPath(fileName);
  509.     if (!actualFile)
  510.     {
  511.       char buf2[400];
  512.       sprintf(buf2, "%s.tex", fileName);
  513.       actualFile = TexPathList.FindValidPath(buf2);
  514.     }
  515.     if (!actualFile)
  516.     {
  517.       char errBuf[300];
  518.       strcpy(errBuf, "Could not find file: ");
  519.       strncat(errBuf, fileName, 100);
  520.       OnError(errBuf);
  521.     }
  522.     else
  523.     {
  524.       CurrentInputIndex ++;
  525.       Inputs[CurrentInputIndex] = fopen(actualFile, "r");
  526.       LineNumbers[CurrentInputIndex] = 1;
  527.       if (FileNames[CurrentInputIndex])
  528.         delete[] FileNames[CurrentInputIndex];
  529.       FileNames[CurrentInputIndex] = copystring(actualFile);
  530.  
  531.       if (!Inputs[CurrentInputIndex])
  532.       {
  533.         CurrentInputIndex --;
  534.         OnError("Could not open include file.");
  535.       }
  536.     }
  537.     Bool succ = read_a_line(buf);
  538.     return succ;
  539.   }
  540.   if (strncmp(buf, "\\begin{verbatim}", 16) == 0 ||
  541.       strncmp(buf, "\\begin{toocomplex}", 18) == 0)
  542.     readInVerbatim = TRUE;
  543.   else if (strncmp(buf, "\\end{verbatim}", 14) == 0 ||
  544.            strncmp(buf, "\\end{toocomplex}", 16) == 0)
  545.     readInVerbatim = FALSE;
  546.  
  547.   return (ch == EOF);
  548. }
  549.  
  550. /*
  551.  * Parse newcommand
  552.  *
  553.  */
  554.  
  555. Bool ParseNewCommand(char *buffer, int *pos)
  556. {
  557.   if ((strncmp((buffer+(*pos)), "newcommand", 10) == 0) ||
  558.       (strncmp((buffer+(*pos)), "renewcommand", 12) == 0))
  559.   {
  560.     if (strncmp((buffer+(*pos)), "newcommand", 10) == 0)
  561.       *pos = *pos + 12;
  562.     else
  563.       *pos = *pos + 14;
  564.  
  565.     char commandName[100];
  566.     char commandValue[1000];
  567.     int noArgs = 0;
  568.     int i = 0;
  569.     while (buffer[*pos] != '}' && (buffer[*pos] != 0))
  570.     {
  571.       commandName[i] = buffer[*pos];
  572.       *pos += 1;
  573.       i ++;
  574.     }
  575.     commandName[i] = 0;
  576.     i = 0;
  577.     *pos += 1;
  578.     if (buffer[*pos] == '[')
  579.     {
  580.       *pos += 1;
  581.       noArgs = (int)(buffer[*pos]) - 48;
  582.       *pos += 2; // read past argument and '['
  583.     }
  584.     Bool end = FALSE;
  585.     Bool braceCount = 0;
  586.     while (!end)
  587.     {
  588.       char ch = buffer[*pos];
  589.       if (ch == '{')
  590.         braceCount ++;
  591.       else if (ch == '}')
  592.       {
  593.         braceCount --;
  594.         if (braceCount == 0)
  595.           end = TRUE;
  596.       }
  597.       else if (ch == 0)
  598.       {
  599.         if (!read_a_line(buffer))
  600.           end = TRUE;
  601.         *pos = 0;
  602.         break;
  603.       }
  604.       commandValue[i] = ch;
  605.       i ++;
  606.       *pos += 1;
  607.     }
  608.     commandValue[i] = 0;
  609.  
  610.     CustomMacro *macro = new CustomMacro(commandName, noArgs, NULL);
  611.     if (strlen(commandValue) > 0)
  612.       macro->macroBody = copystring(commandValue);
  613.     if (!CustomMacroList.Find(commandName))
  614.     {
  615.       CustomMacroList.Append(commandName, macro);
  616.       AddMacroDef(ltCUSTOM_MACRO, commandName, noArgs);
  617.     }
  618.     return TRUE;
  619.   }
  620.   else return FALSE;
  621. }
  622.  
  623. void MacroError(char *buffer)
  624. {
  625.   char errBuf[300];
  626.   char macroBuf[200];
  627.   macroBuf[0] = '\\';
  628.   int i = 1;
  629.   char ch;
  630.   while (((ch = buffer[i-1]) != '\n') && (ch != 0))
  631.   {
  632.     macroBuf[i] = ch;
  633.     i ++;
  634.   }
  635.   macroBuf[i] = 0;
  636.   if (i > 20)
  637.     macroBuf[20] = 0;
  638.  
  639.   sprintf(errBuf, "Could not find macro: %s at line %d, file %s",
  640.              macroBuf, (int)(LineNumbers[CurrentInputIndex]-1), FileNames[CurrentInputIndex]);
  641.   OnError(errBuf);
  642. }
  643.  
  644. /*
  645.  * Parse an argument.
  646.  * 'environment' specifies the name of the macro IFF if we're looking for the end
  647.  * of an environment, e.g. \end{itemize}. Otherwise it's NULL.
  648.  * 'parseToBrace' is TRUE if the argument should extend to the next right brace,
  649.  * e.g. in {\bf an argument} as opposed to \vskip 30pt
  650.  *
  651.  */
  652. int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *environment, Bool parseToBrace, TexChunk *customMacroArgs)
  653. {
  654.   Tex2RTFYield();
  655.   if (stopRunning) return pos;
  656.   
  657.   Bool eof = FALSE;
  658.   BigBuffer[0] = 0;
  659.   int buf_ptr = 0;
  660.   int len;
  661.  
  662. /*
  663.  
  664.   // Consume leading brace or square bracket, but ONLY if not following
  665.   // a space, because this could be e.g. {\large {\bf thing}} where {\bf thing}
  666.   // is the argument of \large AS WELL as being a block in its
  667.   // own right.
  668.   if (!environment)
  669.   {
  670.     if ((pos > 0) && (buffer[pos-1] != ' ') && buffer[pos] == '{')
  671.       pos ++;
  672.     else
  673.  
  674.     if ((pos > 0) && (buffer[pos-1] != ' ') && (buffer[pos] == '[' || buffer[pos] == '('))
  675.     {
  676.       isOptional = TRUE;
  677.       pos ++;
  678.     }
  679.     else if ((pos > 1) && (buffer[pos-1] != ' ') && (buffer[pos+1] == '[' || buffer[pos+1] == '('))
  680.     {
  681.       isOptional = TRUE;
  682.       pos += 2;
  683.     }
  684.   }
  685. */
  686.     
  687.   // If not parsing to brace, just read the next word
  688.   // (e.g. \vskip 20pt)
  689.   if (!parseToBrace)
  690.   {
  691.     int ch = buffer[pos];
  692.     while (!eof && ch != 13 && ch != 32 && ch != 10 &&
  693.            ch != 0 && ch != '{')
  694.     {
  695.       BigBuffer[buf_ptr] = ch;
  696.       buf_ptr ++;
  697.       pos ++;
  698.       ch = buffer[pos];
  699.     }
  700.     if (buf_ptr > 0)
  701.     {
  702.       TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  703.       BigBuffer[buf_ptr] = 0;
  704.       buf_ptr = 0;
  705.       chunk->value = copystring(BigBuffer);
  706.       children.Append((wxObject *)chunk);
  707.     }
  708.     return pos;
  709.   }
  710.  
  711.   while (!eof)
  712.   {
  713.     len = strlen(buffer);
  714.     if (pos >= len)
  715.     {
  716.       if (customMacroArgs) return 0;
  717.  
  718.       eof = read_a_line(buffer);
  719.       pos = 0;
  720.       len = strlen(buffer);
  721.       // Check for verbatim (or toocomplex, which comes to the same thing)
  722.       if (strncmp(buffer, "\\begin{verbatim}", 16) == 0 ||
  723.           strncmp(buffer, "\\begin{toocomplex}", 18) == 0)
  724.       {
  725.         if (buf_ptr > 0)
  726.         {
  727.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  728.           BigBuffer[buf_ptr] = 0;
  729.           buf_ptr = 0;
  730.           chunk->value = copystring(BigBuffer);
  731.           children.Append((wxObject *)chunk);
  732.         }
  733.         BigBuffer[0] = 0;
  734.         buf_ptr = 0;
  735.  
  736.         eof = read_a_line(buffer);
  737.         while (!eof && (strncmp(buffer, "\\end{verbatim}", 14) != 0) &&
  738.                        (strncmp(buffer, "\\end{toocomplex}", 16) != 0)
  739.                )
  740.     {
  741.           strcat(BigBuffer, buffer);
  742.           buf_ptr += strlen(buffer);
  743.           eof = read_a_line(buffer);
  744.     }
  745.         eof = read_a_line(buffer);
  746.         buf_ptr = 0;
  747.  
  748.         TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO, VerbatimMacroDef);
  749.         chunk->no_args = 1;
  750.         chunk->macroId = ltVERBATIM;
  751.         TexChunk *arg = new TexChunk(CHUNK_TYPE_ARG, VerbatimMacroDef);
  752.         arg->argn = 1;
  753.         arg->macroId = ltVERBATIM;
  754.         TexChunk *str = new TexChunk(CHUNK_TYPE_STRING);
  755.         str->value = copystring(BigBuffer);
  756.  
  757.         children.Append((wxObject *)chunk);
  758.         chunk->children.Append((wxObject *)arg);
  759.         arg->children.Append((wxObject *)str);
  760.  
  761.         // Also want to include the following newline (is always a newline
  762.         // after a verbatim).
  763.         TexMacroDef *parDef = (TexMacroDef *)MacroDefs.Get("\\");
  764.         TexChunk *parChunk = new TexChunk(CHUNK_TYPE_MACRO, parDef);
  765.         parChunk->no_args = 0;
  766.         parChunk->macroId = ltBACKSLASHCHAR;
  767.         children.Append((wxObject *)parChunk);
  768.       }
  769.     }
  770.  
  771.     char ch = buffer[pos];
  772.     // End of optional argument -- pretend it's right brace for simplicity
  773.     if (thisArg->optional && (ch == ']'))
  774.       ch = '}';
  775.  
  776.     switch (ch)
  777.     {
  778.       case 0:
  779.       case '}':  // End of argument
  780.       {
  781.         if (buf_ptr > 0)
  782.         {
  783.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  784.           BigBuffer[buf_ptr] = 0;
  785.           buf_ptr = 0;
  786.           chunk->value = copystring(BigBuffer);
  787.           children.Append((wxObject *)chunk);
  788.         }
  789.         if (ch == '}') pos ++;
  790.         return pos;
  791.         break;
  792.       }
  793.       case '\\':
  794.       {
  795.         if (buf_ptr > 0)  // Finish off the string we've read so far
  796.         {
  797.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  798.           BigBuffer[buf_ptr] = 0;
  799.           buf_ptr = 0;
  800.           chunk->value = copystring(BigBuffer);
  801.           children.Append((wxObject *)chunk);
  802.         }
  803.         pos ++;
  804.         
  805.  
  806.         // Try matching \end{environment}
  807.         if (environment && FindEndEnvironment(buffer, &pos, environment))
  808.         {
  809.           // Eliminate newline after an \end{} if possible
  810.           if (buffer[pos] == 13)
  811.           {
  812.             pos ++;
  813.             if (buffer[pos] == 10)
  814.               pos ++;
  815.           }
  816.           return pos;
  817.         }
  818.  
  819.         if (ParseNewCommand(buffer, &pos))
  820.           break;
  821.  
  822.         if (strncmp(buffer+pos, "special", 7) == 0)
  823.         {
  824.           pos += 7;
  825.  
  826.           // Discard {
  827.           pos ++;
  828.           int noBraces = 1;
  829.  
  830.           wxBuffer[0] = 0;
  831.           int i = 0;
  832.           Bool end = FALSE;
  833.           while (!end)
  834.           {
  835.             int ch = buffer[pos];
  836.             if (ch == '}')
  837.             {
  838.               noBraces --;
  839.               if (noBraces == 0)
  840.               {
  841.                 wxBuffer[i] = 0;
  842.                 end = TRUE;
  843.               }
  844.               else
  845.               {
  846.                 wxBuffer[i] = '}';
  847.                 i ++;
  848.               }
  849.               pos ++;
  850.             }
  851.             else if (ch == '{')
  852.             {
  853.               wxBuffer[i] = '{';
  854.               i ++;
  855.               pos ++;
  856.             }
  857.             else if (ch == '\\' && buffer[pos+1] == '}')
  858.             {
  859.               wxBuffer[i] = '}';
  860.               pos += 2;
  861.               i++;
  862.             }
  863.             else if (ch == '\\' && buffer[pos+1] == '{')
  864.             {
  865.               wxBuffer[i] = '{';
  866.               pos += 2;
  867.               i++;
  868.             }
  869.             else
  870.             {
  871.               wxBuffer[i] = ch;
  872.               pos ++;
  873.               i ++;
  874.               if (ch == 0)
  875.                 end = TRUE;
  876.             }
  877.           }
  878.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
  879.           chunk->no_args = 1;
  880.           chunk->macroId = ltSPECIAL;
  881.           TexMacroDef *specialDef = (TexMacroDef *)MacroDefs.Get("special");
  882.           chunk->def = specialDef;
  883.           TexChunk *arg = new TexChunk(CHUNK_TYPE_ARG, specialDef);
  884.           chunk->children.Append((wxObject *)arg);
  885.           arg->argn = 1;
  886.           arg->macroId = chunk->macroId;
  887.  
  888.           // The value in the first argument.
  889.           TexChunk *argValue = new TexChunk(CHUNK_TYPE_STRING);
  890.           arg->children.Append((wxObject *)argValue);
  891.           argValue->argn = 1;
  892.           argValue->value = copystring(wxBuffer);
  893.  
  894.           children.Append((wxObject *)chunk);
  895.         }
  896.         else if (strncmp(buffer+pos, "verb", 4) == 0)
  897.         {
  898.           pos += 4;
  899.           if (buffer[pos] == '*')
  900.             pos ++;
  901.  
  902.           // Find the delimiter character         
  903.           int ch = buffer[pos];
  904.           pos ++;
  905.           // Now at start of verbatim text
  906.           int j = pos;
  907.           while ((buffer[pos] != ch) && buffer[pos] != 0)
  908.             pos ++;
  909.           char *val = new char[pos - j + 1];
  910.           for (int i = j; i < pos; i++)
  911.           {
  912.             val[i-j] = buffer[i];
  913.           }
  914.           val[i-j] = 0;
  915.  
  916.           pos ++;
  917.  
  918.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
  919.           chunk->no_args = 1;
  920.           chunk->macroId = ltVERB;
  921.           TexMacroDef *verbDef = (TexMacroDef *)MacroDefs.Get("verb");
  922.           chunk->def = verbDef;
  923.           TexChunk *arg = new TexChunk(CHUNK_TYPE_ARG, verbDef);
  924.           chunk->children.Append((wxObject *)arg);
  925.           arg->argn = 1;
  926.           arg->macroId = chunk->macroId;
  927.  
  928.           // The value in the first argument.
  929.           TexChunk *argValue = new TexChunk(CHUNK_TYPE_STRING);
  930.           arg->children.Append((wxObject *)argValue);
  931.           argValue->argn = 1;
  932.           argValue->value = val;
  933.  
  934.           children.Append((wxObject *)chunk);
  935.         }
  936.     else
  937.     {
  938.           char *env = NULL;
  939.           Bool tmpParseToBrace = TRUE;
  940.           TexMacroDef *def = MatchMacro(buffer, &pos, &env, &tmpParseToBrace);
  941.           if (def)
  942.           {
  943.           CustomMacro *customMacro = FindCustomMacro(def->name);
  944.  
  945.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO, def);
  946.           chunk->no_args = def->no_args;
  947. //          chunk->name = copystring(def->name);
  948.           chunk->macroId = def->macroId;
  949.  
  950.           if  (!customMacro)
  951.             children.Append((wxObject *)chunk);
  952.  
  953.           // Eliminate newline after a \begin{} or a \\ if possible
  954.           if (env || strcmp(def->name, "\\") == 0)
  955.             if (buffer[pos] == 13)
  956.             {
  957.               pos ++;
  958.               if (buffer[pos] == 10)
  959.                 pos ++;
  960.             }
  961.  
  962.           pos = ParseMacroBody(def->name, chunk, chunk->no_args,
  963.                      buffer, pos, env, tmpParseToBrace, customMacroArgs);
  964.  
  965.           // If custom macro, parse the body substituting the above found args.
  966.           if (customMacro)
  967.           {
  968.             if (customMacro->macroBody)
  969.             {
  970.               char macroBuf[300];
  971. //              strcpy(macroBuf, "{");
  972.               strcpy(macroBuf, customMacro->macroBody);
  973.               strcat(macroBuf, "}");
  974.               ParseArg(thisArg, children, macroBuf, 0, NULL, TRUE, chunk);
  975.             }
  976.             
  977. //            delete chunk; // Might delete children
  978.           }
  979.         }
  980.         else
  981.         {
  982.           MacroError(buffer+pos);
  983.         }
  984.         }
  985.         break;
  986.       }
  987.       // Parse constructs like {\bf thing} as if they were
  988.       // \bf{thing}
  989.       case '{':
  990.       {
  991.         pos ++;
  992.         if (buffer[pos] == '\\')
  993.         {
  994.           if (buf_ptr > 0)
  995.           {
  996.             TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  997.             BigBuffer[buf_ptr] = 0;
  998.             buf_ptr = 0;
  999.             chunk->value = copystring(BigBuffer);
  1000.             children.Append((wxObject *)chunk);
  1001.           }
  1002.           pos ++;
  1003.  
  1004.           char *env;
  1005.           Bool tmpParseToBrace;
  1006.           TexMacroDef *def = MatchMacro(buffer, &pos, &env, &tmpParseToBrace);
  1007.           if (def)
  1008.           {
  1009.             CustomMacro *customMacro = FindCustomMacro(def->name);
  1010.  
  1011.             TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO, def);
  1012.             chunk->no_args = def->no_args;
  1013. //            chunk->name = copystring(def->name);
  1014.             chunk->macroId = def->macroId;
  1015.             if (!customMacro)
  1016.               children.Append((wxObject *)chunk);
  1017.  
  1018.             pos = ParseMacroBody(def->name, chunk, chunk->no_args,
  1019.                        buffer, pos, NULL, TRUE, customMacroArgs);
  1020.  
  1021.             // If custom macro, parse the body substituting the above found args.
  1022.             if (customMacro)
  1023.             {
  1024.               if (customMacro->macroBody)
  1025.               {
  1026.                 char macroBuf[300];
  1027. //                strcpy(macroBuf, "{");
  1028.                 strcpy(macroBuf, customMacro->macroBody);
  1029.                 strcat(macroBuf, "}");
  1030.                 ParseArg(thisArg, children, macroBuf, 0, NULL, TRUE, chunk);
  1031.               }
  1032.             
  1033. //            delete chunk; // Might delete children
  1034.         }
  1035.           }
  1036.           else
  1037.           {
  1038.             MacroError(buffer+pos);
  1039.           }
  1040.         }
  1041.         else
  1042.     {
  1043.          /*
  1044.           * If all else fails, we assume that we have
  1045.           * a pair of braces on their own, so return a `dummy' macro
  1046.           * definition with just one argument to parse.
  1047.           */
  1048.           if (!SoloBlockDef)
  1049.           {
  1050.             SoloBlockDef = new TexMacroDef(ltSOLO_BLOCK, "solo block", 1, FALSE);
  1051.           }
  1052.           // Save text so far
  1053.           if (buf_ptr > 0)
  1054.           {
  1055.             TexChunk *chunk1 = new TexChunk(CHUNK_TYPE_STRING);
  1056.             BigBuffer[buf_ptr] = 0;
  1057.             buf_ptr = 0;
  1058.             chunk1->value = copystring(BigBuffer);
  1059.             children.Append((wxObject *)chunk1);
  1060.           }
  1061.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO, SoloBlockDef);
  1062.           chunk->no_args = SoloBlockDef->no_args;
  1063. //          chunk->name = copystring(SoloBlockDef->name);
  1064.           chunk->macroId = SoloBlockDef->macroId;
  1065.           children.Append((wxObject *)chunk);
  1066.  
  1067.           TexChunk *arg = new TexChunk(CHUNK_TYPE_ARG, SoloBlockDef);
  1068.  
  1069.           chunk->children.Append((wxObject *)arg);
  1070. //          arg->name = copystring(SoloBlockDef->name);
  1071.           arg->argn = 1;
  1072.           arg->macroId = chunk->macroId;
  1073.  
  1074.           pos = ParseArg(arg, arg->children, buffer, pos, NULL, TRUE, customMacroArgs);
  1075.     }
  1076.         break;
  1077.       }
  1078.       case '$':
  1079.       {
  1080.         if (buf_ptr > 0)
  1081.         {
  1082.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  1083.           BigBuffer[buf_ptr] = 0;
  1084.           buf_ptr = 0;
  1085.           chunk->value = copystring(BigBuffer);
  1086.           children.Append((wxObject *)chunk);
  1087.         }
  1088.  
  1089.         pos ++;
  1090.  
  1091.         if (buffer[pos] == '$')
  1092.         {
  1093.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
  1094.           chunk->no_args = 0;
  1095. //          chunk->name = copystring("$$");
  1096.           chunk->macroId = ltSPECIALDOUBLEDOLLAR;
  1097.           children.Append((wxObject *)chunk);
  1098.           pos ++;
  1099.         }
  1100.         else
  1101.         {
  1102.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
  1103.           chunk->no_args = 0;
  1104. //          chunk->name = copystring("_$");
  1105.           chunk->macroId = ltSPECIALDOLLAR;
  1106.           children.Append((wxObject *)chunk);
  1107.         }
  1108.         break;
  1109.       }
  1110.       case '~':
  1111.       {
  1112.         if (buf_ptr > 0)
  1113.         {
  1114.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  1115.           BigBuffer[buf_ptr] = 0;
  1116.           buf_ptr = 0;
  1117.           chunk->value = copystring(BigBuffer);
  1118.           children.Append((wxObject *)chunk);
  1119.         }
  1120.  
  1121.         pos ++;
  1122.         TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
  1123.         chunk->no_args = 0;
  1124. //        chunk->name = copystring("_~");
  1125.         chunk->macroId = ltSPECIALTILDE;
  1126.         children.Append((wxObject *)chunk);
  1127.         break;
  1128.       }
  1129.       case '#': // Either treat as a special TeX character or as a macro arg
  1130.       {
  1131.         if (buf_ptr > 0)
  1132.         {
  1133.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  1134.           BigBuffer[buf_ptr] = 0;
  1135.           buf_ptr = 0;
  1136.           chunk->value = copystring(BigBuffer);
  1137.           children.Append((wxObject *)chunk);
  1138.         }
  1139.  
  1140.         pos ++;
  1141.         if (!customMacroArgs)
  1142.         {
  1143.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
  1144.           chunk->no_args = 0;
  1145. //          chunk->name = copystring("_#");
  1146.           chunk->macroId = ltSPECIALHASH;
  1147.           children.Append((wxObject *)chunk);
  1148.         }
  1149.         else
  1150.         {
  1151.           if (isdigit(buffer[pos]))
  1152.           {
  1153.             int n = buffer[pos] - 48;
  1154.             pos ++;
  1155.             wxNode *node = customMacroArgs->children.Nth(n-1);
  1156.             if (node)
  1157.             {
  1158.               TexChunk *argChunk = (TexChunk *)node->Data();
  1159.               children.Append((wxObject *)new TexChunk(*argChunk));
  1160.             }
  1161.           }
  1162.         }
  1163.         break;
  1164.       }
  1165.       case '&':
  1166.       {
  1167.         // Remove white space before and after the ampersand,
  1168.         // since this is probably a table column separator with
  1169.         // some convenient -- but useless -- white space in the text.
  1170.         while ((buf_ptr > 0) && ((BigBuffer[buf_ptr-1] == ' ') || (BigBuffer[buf_ptr-1] == 9)))
  1171.           buf_ptr --;
  1172.  
  1173.         if (buf_ptr > 0)
  1174.         {
  1175.           TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
  1176.           BigBuffer[buf_ptr] = 0;
  1177.           buf_ptr = 0;
  1178.           chunk->value = copystring(BigBuffer);
  1179.           children.Append((wxObject *)chunk);
  1180.         }
  1181.  
  1182.         pos ++;
  1183.  
  1184.         while (buffer[pos] == ' ' || buffer[pos] == 9)
  1185.           pos ++;
  1186.  
  1187.         TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
  1188.         chunk->no_args = 0;
  1189. //        chunk->name = copystring("_&");
  1190.         chunk->macroId = ltSPECIALAMPERSAND;
  1191.         children.Append((wxObject *)chunk);
  1192.         break;
  1193.       }
  1194.       // Eliminate end-of-line comment
  1195.       case '%':
  1196.       {
  1197.         ch = buffer[pos];
  1198.         while (ch != 10 && ch != 13 && ch != 0)
  1199.         {
  1200.           pos ++;
  1201.           ch = buffer[pos];
  1202.         }
  1203.         if (buffer[pos] == 10 || buffer[pos] == 13)
  1204.         {
  1205.           pos ++;
  1206.           if (buffer[pos] == 10) pos ++; // Eliminate newline following DOS line feed
  1207.         }
  1208.         break;
  1209.       }
  1210.       // Eliminate tab
  1211.       case 9:
  1212.       {
  1213.         BigBuffer[buf_ptr] = ' ';
  1214.         BigBuffer[buf_ptr+1] = 0;
  1215.         buf_ptr ++;
  1216.         pos ++;
  1217.         break;
  1218.       }
  1219.       default:
  1220.       {
  1221.         BigBuffer[buf_ptr] = ch;
  1222.         BigBuffer[buf_ptr+1] = 0;
  1223.         buf_ptr ++;
  1224.         pos ++;
  1225.         break;
  1226.       }
  1227.     }
  1228.   }
  1229.   return pos;
  1230. }
  1231.  
  1232. /*
  1233.  * Consume as many arguments as the macro definition specifies
  1234.  *
  1235.  */
  1236.  
  1237. int ParseMacroBody(char *macro_name, TexChunk *parent,
  1238.                    int no_args, char *buffer, int pos,
  1239.                    char *environment, Bool parseToBrace,
  1240.                    TexChunk *customMacroArgs)
  1241. {
  1242.   Tex2RTFYield();
  1243.   if (stopRunning) pos;
  1244.  
  1245.   // Check for a first optional argument
  1246.   if (buffer[pos] == ' ' && buffer[pos+1] == '[')
  1247.   {
  1248.     // Fool following code into thinking that this is definitely
  1249.     // an optional first argument. (If a space before a non-first argument,
  1250.     // [ is interpreted as a [, not an optional argument.)
  1251.     buffer[pos] = '!';
  1252.     pos ++;
  1253.     no_args ++;
  1254.   }
  1255.   else
  1256.     if (buffer[pos] == '[')
  1257.       no_args ++;
  1258.  
  1259.   int maxArgs = 0;
  1260.  
  1261.   for (int i = 0; i < no_args; i++)
  1262.   {
  1263.     maxArgs ++;
  1264.     TexChunk *arg = new TexChunk(CHUNK_TYPE_ARG, parent->def);
  1265.  
  1266.     parent->children.Append((wxObject *)arg);
  1267. //    arg->name = copystring(macro_name);
  1268.     arg->argn = maxArgs;
  1269.     arg->macroId = parent->macroId;
  1270.  
  1271.     // To parse the first arg of a 2 arg \begin{thing}{arg} ... \end{thing}
  1272.     // have to fool parser into thinking this is a regular kind of block.
  1273.     char *actualEnv;
  1274.     if ((no_args == 2) && (i == 0))
  1275.       actualEnv = NULL;
  1276.     else
  1277.       actualEnv = environment;
  1278.  
  1279.     Bool isOptional = FALSE;
  1280.  
  1281.     // Remove the first { of the argument so it doesn't get recognized as { ... }
  1282. //    EatWhiteSpace(buffer, &pos);
  1283.     if (!actualEnv)
  1284.     {
  1285.       // The reason for these tests is to not consume braces that don't
  1286.       // belong to this macro.
  1287.       // E.g. {\bf {\small thing}}
  1288.       if ((pos > 0) && (buffer[pos-1] != ' ') && buffer[pos] == '{')
  1289.         pos ++;
  1290.       else
  1291.       if ((pos > 0) && (buffer[pos-1] != ' ') && (buffer[pos] == '['))
  1292.       {
  1293.         isOptional = TRUE;
  1294.         pos ++;
  1295.       }
  1296.       else if ((pos > 1) && (buffer[pos-1] != ' ') && (buffer[pos+1] == '['))
  1297.       {
  1298.         isOptional = TRUE;
  1299.         pos += 2;
  1300.       }
  1301.     }
  1302.     arg->optional = isOptional;
  1303.  
  1304.     pos = ParseArg(arg, arg->children, buffer, pos, actualEnv, parseToBrace, customMacroArgs);
  1305.  
  1306.     // If we've encountered an OPTIONAL argument, go another time around
  1307.     // the loop, because we've got more than we thought.
  1308.     // Hopefully optional args don't occur at the end of a macro use
  1309.     // or we might miss it.
  1310.     // Don't increment no of times round loop if the first optional arg
  1311.     // -- we already did it before the loop.
  1312.     if (arg->optional && (i > 0))
  1313.       i --;
  1314.   }
  1315.   parent->no_args = maxArgs;
  1316.  
  1317.   // Tell each argument how many args there are (useful when processing an arg)
  1318.   wxNode *node = parent->children.First();
  1319.   while (node)
  1320.   {
  1321.     TexChunk *chunk = (TexChunk *)node->Data();
  1322.     chunk->no_args = maxArgs;
  1323.     node = node->Next();
  1324.   }
  1325.   return pos;
  1326. }
  1327.  
  1328. Bool TexLoadFile(char *filename)
  1329. {
  1330.   stopRunning = FALSE;
  1331.   strcpy(TexFileRoot, filename);
  1332.   StripExtension(TexFileRoot);
  1333.   sprintf(TexBibName, "%s.bb", TexFileRoot);
  1334.   sprintf(TexTmpBibName, "%s.bb1", TexFileRoot);
  1335.  
  1336.   TexPathList.EnsureFileAccessible(filename);
  1337.  
  1338. #ifdef wx_msw
  1339.   static char *line_buffer = new char[600];
  1340. #else
  1341.   static char *line_buffer = new char[11000];
  1342. #endif
  1343.   
  1344.   Inputs[0] = fopen(filename, "r");
  1345.   LineNumbers[0] = 1;
  1346.   FileNames[0] = copystring(filename);
  1347.   if (Inputs[0])
  1348.   {
  1349.     read_a_line(line_buffer);
  1350.     ParseMacroBody("toplevel", TopLevel, 1, line_buffer, 0, NULL, TRUE);
  1351.     if (Inputs[0]) fclose(Inputs[0]);
  1352.     return TRUE;
  1353.   }
  1354.   else return FALSE;
  1355. }
  1356.  
  1357. TexMacroDef::TexMacroDef(int the_id, char *the_name, int n, Bool ig, Bool forbidLevel)
  1358. {
  1359.   name = copystring(the_name);
  1360.   no_args = n;
  1361.   ignore = ig;
  1362.   macroId = the_id;
  1363.   forbidden = forbidLevel;
  1364. }
  1365.  
  1366. TexMacroDef::~TexMacroDef(void)
  1367. {
  1368.   if (name) delete[] name;
  1369. }
  1370.  
  1371. TexChunk::TexChunk(int the_type, TexMacroDef *the_def)
  1372. {
  1373.   type = the_type;
  1374.   no_args = 0;
  1375.   argn = 0;
  1376. //  name = NULL;
  1377.   def = the_def;
  1378.   macroId = 0;
  1379.   value = NULL;
  1380.   optional = FALSE;
  1381. }
  1382.  
  1383. TexChunk::TexChunk(TexChunk& toCopy)
  1384. {
  1385.   type = toCopy.type;
  1386.   no_args = toCopy.no_args;
  1387.   argn = toCopy.argn;
  1388.   macroId = toCopy.macroId;
  1389.   
  1390. //  if (toCopy.name)
  1391. //    name = copystring(toCopy.name);
  1392. //  else
  1393. //    name = NULL;
  1394.   def = toCopy.def;
  1395.  
  1396.   if (toCopy.value)
  1397.     value = copystring(toCopy.value);
  1398.   else
  1399.     value = NULL;
  1400.   
  1401.   optional = toCopy.optional;
  1402.   wxNode *node = toCopy.children.First();
  1403.   while (node)
  1404.   {
  1405.     TexChunk *child = (TexChunk *)node->Data();
  1406.     children.Append((wxObject *)new TexChunk(*child));
  1407.     node = node->Next();
  1408.   }
  1409. }
  1410.  
  1411. TexChunk::~TexChunk(void)
  1412. {
  1413. //  if (name) delete[] name;
  1414.   if (value) delete[] value;
  1415.   wxNode *node = children.First();
  1416.   while (node)
  1417.   {
  1418.     TexChunk *child = (TexChunk *)node->Data();
  1419.     delete child;
  1420.     wxNode *next = node->Next();
  1421.     delete node;
  1422.     node = next;
  1423.   }
  1424. }
  1425.  
  1426. Bool IsArgOptional(void)  // Is this argument an optional argument?
  1427. {
  1428.   return isArgOptional;
  1429. }
  1430.  
  1431. int GetNoArgs(void) // Number of args for this macro
  1432. {
  1433.   return noArgs;
  1434. }
  1435.  
  1436. /* Gets the text of a chunk on request (must be for small arguments
  1437.  * only!)
  1438.  *
  1439.  */
  1440.  
  1441. void GetArgData1(TexChunk *chunk)
  1442. {
  1443.   switch (chunk->type)
  1444.   {
  1445.     case CHUNK_TYPE_MACRO:
  1446.     {
  1447.       TexMacroDef *def = chunk->def;
  1448.       if (def && def->ignore)
  1449.         return;
  1450.  
  1451.       if (def && (strcmp(def->name, "solo block") != 0))
  1452.       {
  1453.         strcat(currentArgData, "\\");
  1454.         strcat(currentArgData, def->name);
  1455.       }
  1456.  
  1457.       wxNode *node = chunk->children.First();
  1458.       while (node)
  1459.       {
  1460.         TexChunk *child_chunk = (TexChunk *)node->Data();
  1461.         strcat(currentArgData, "{");
  1462.         GetArgData1(child_chunk);
  1463.         strcat(currentArgData, "}");
  1464.         node = node->Next();
  1465.       }
  1466.       break;
  1467.     }
  1468.     case CHUNK_TYPE_ARG:
  1469.     {
  1470.       wxNode *node = chunk->children.First();
  1471.       while (node)
  1472.       {
  1473.         TexChunk *child_chunk = (TexChunk *)node->Data();
  1474.         GetArgData1(child_chunk);
  1475.         node = node->Next();
  1476.       }
  1477.       break;
  1478.     }
  1479.     case CHUNK_TYPE_STRING:
  1480.     {
  1481.       if (chunk->value)
  1482.         strcat(currentArgData, chunk->value);
  1483.       break;
  1484.     }
  1485.   }
  1486. }
  1487.  
  1488. char *GetArgData(TexChunk *chunk)
  1489. {
  1490.   currentArgData[0] = 0;
  1491.   GetArgData1(currentArgument);
  1492.   haveArgData = FALSE;
  1493.   return currentArgData;
  1494. }
  1495.  
  1496. char *GetArgData(void)
  1497. {
  1498.   if (!haveArgData)
  1499.   {
  1500.     currentArgData[0] = 0;
  1501.     GetArgData1(currentArgument);
  1502.   }
  1503.   return currentArgData;
  1504. }
  1505.  
  1506. TexChunk *GetArgChunk(void)
  1507. {
  1508.   return currentArgument;
  1509. }
  1510.  
  1511. TexChunk *GetNextChunk(void)     // Look ahead to the next chunk
  1512. {
  1513.   return nextChunk;
  1514. }
  1515.  
  1516. TexChunk *GetTopLevelChunk(void)
  1517. {
  1518.   return TopLevel;
  1519. }
  1520.  
  1521. int GetCurrentColumn(void)
  1522. {
  1523.   return currentColumn;
  1524. }
  1525.  
  1526. /*
  1527.  * Traverses document calling functions to allow the client to
  1528.  * write out the appropriate stuff
  1529.  */
  1530.  
  1531.  
  1532. void TraverseFromChunk(TexChunk *chunk, wxNode *thisNode, Bool childrenOnly)
  1533. {
  1534.   Tex2RTFYield();
  1535.   if (stopRunning) return;
  1536.  
  1537.   switch (chunk->type)
  1538.   {
  1539.     case CHUNK_TYPE_MACRO:
  1540.     {
  1541.       TexMacroDef *def = chunk->def;
  1542.       if (def && def->ignore)
  1543.         return;
  1544.  
  1545.       if (!childrenOnly)
  1546.         OnMacro(chunk->macroId, chunk->no_args, TRUE);
  1547.  
  1548.       wxNode *node = chunk->children.First();
  1549.       while (node)
  1550.       {
  1551.         TexChunk *child_chunk = (TexChunk *)node->Data();
  1552.         TraverseFromChunk(child_chunk, node);
  1553.         node = node->Next();
  1554.       }
  1555.  
  1556.       if (thisNode && thisNode->Next()) nextChunk = (TexChunk *)thisNode->Next()->Data();
  1557.  
  1558.       if (!childrenOnly)
  1559.         OnMacro(chunk->macroId, chunk->no_args, FALSE);
  1560.       break;
  1561.     }
  1562.     case CHUNK_TYPE_ARG:
  1563.     {
  1564.       currentArgument = chunk;
  1565.  
  1566.       isArgOptional = chunk->optional;
  1567.       noArgs = chunk->no_args;
  1568.  
  1569.       // If OnArgument returns FALSE, don't output.
  1570.  
  1571.       if (childrenOnly || OnArgument(chunk->macroId, chunk->argn, TRUE))
  1572.       {
  1573.         wxNode *node = chunk->children.First();
  1574.         while (node)
  1575.         {
  1576.           TexChunk *child_chunk = (TexChunk *)node->Data();
  1577.           TraverseFromChunk(child_chunk, node);
  1578.           node = node->Next();
  1579.         }
  1580.       }
  1581.  
  1582.       currentArgument = chunk;
  1583.  
  1584.       if (thisNode && thisNode->Next()) nextChunk = (TexChunk *)thisNode->Next()->Data();
  1585.  
  1586.       isArgOptional = chunk->optional;
  1587.       noArgs = chunk->no_args;
  1588.  
  1589.       if (!childrenOnly)
  1590.         (void)OnArgument(chunk->macroId, chunk->argn, FALSE);
  1591.       break;
  1592.     }
  1593.     case CHUNK_TYPE_STRING:
  1594.     {
  1595.       extern Bool issuedNewParagraph;
  1596.       extern int forbidResetPar;
  1597.       if (chunk->value && (forbidResetPar == 0))
  1598.       {
  1599.         // If non-whitespace text, we no longer have a new paragraph.
  1600.         if (issuedNewParagraph && !((chunk->value[0] == 10 || chunk->value[0] == 13 || chunk->value[0] == 32)
  1601.                                     && chunk->value[1] == 0))
  1602.           issuedNewParagraph = FALSE;
  1603.         TexOutput(chunk->value, TRUE);
  1604.       }
  1605.       break;
  1606.     }
  1607.   }
  1608. }
  1609.  
  1610. void TraverseDocument(void)
  1611. {
  1612.   TraverseFromChunk(TopLevel, NULL);
  1613. }
  1614.  
  1615. void SetCurrentOutput(FILE *fd)
  1616. {
  1617.   CurrentOutput1 = fd;
  1618.   CurrentOutput2 = NULL;
  1619. }
  1620.  
  1621. void SetCurrentOutputs(FILE *fd1, FILE *fd2)
  1622. {
  1623.   CurrentOutput1 = fd1;
  1624.   CurrentOutput2 = fd2;
  1625. }
  1626.  
  1627. void AddMacroDef(int the_id, char *name, int n, Bool ignore, Bool forbid)
  1628. {
  1629.   MacroDefs.Put(name, new TexMacroDef(the_id, name, n, ignore, forbid));
  1630. }
  1631.  
  1632. void TexInitialize(int bufSize)
  1633. {
  1634.   InitialiseColourTable();
  1635. #ifdef wx_msw
  1636.   TexPathList.AddEnvList("TEXINPUT");
  1637. #endif
  1638. #ifdef wx_x
  1639.   TexPathList.AddEnvList("TEXINPUTS");
  1640. #endif
  1641.   for (int i = 0; i < 15; i++)
  1642.   {
  1643.     Inputs[i] = NULL;
  1644.     LineNumbers[i] = 1;
  1645.     FileNames[i] = NULL;
  1646.   }
  1647.  
  1648.   IgnorableInputFiles.Add("psbox.tex");
  1649.   BigBuffer = new char[(bufSize*1000)];
  1650.   currentArgData = new char[2000];
  1651.   TexFileRoot = new char[300];
  1652.   TexBibName = new char[300];
  1653.   TexTmpBibName = new char[300];
  1654.   AddMacroDef(ltTOPLEVEL, "toplevel", 1);
  1655.   TopLevel = new TexChunk(CHUNK_TYPE_MACRO);
  1656. //  TopLevel->name = copystring("toplevel");
  1657.   TopLevel->macroId = ltTOPLEVEL;
  1658.   TopLevel->no_args = 1;
  1659.   VerbatimMacroDef = (TexMacroDef *)MacroDefs.Get("verbatim");
  1660. }
  1661.  
  1662. void TexCleanUp(void)
  1663. {
  1664.   for (int i = 0; i < 15; i++)
  1665.     Inputs[i] = NULL;
  1666.  
  1667.   chapterNo = 0;
  1668.   sectionNo = 0;
  1669.   subsectionNo = 0;
  1670.   subsubsectionNo = 0;
  1671.   figureNo = 0;
  1672.  
  1673.   CurrentOutput1 = NULL;
  1674.   CurrentOutput2 = NULL;
  1675.   CurrentInputIndex = 0;
  1676.   haveArgData = FALSE;
  1677.   noArgs = 0;
  1678.  
  1679.   if (TopLevel)
  1680.     delete TopLevel;
  1681.   TopLevel = new TexChunk(CHUNK_TYPE_MACRO);
  1682. //  TopLevel->name = copystring("toplevel");
  1683.   TopLevel->macroId = ltTOPLEVEL;
  1684.   TopLevel->no_args = 1;
  1685.  
  1686.   DocumentTitle = NULL;
  1687.   DocumentAuthor = NULL;
  1688.   DocumentDate = NULL;
  1689.   DocumentStyle = LATEX_REPORT;
  1690.   MinorDocumentStyle = 0;
  1691.   BibliographyStyleString = copystring("plain");
  1692.   DocumentStyleString = copystring("report");
  1693.   MinorDocumentStyleString = NULL;
  1694. /* Don't want to remove custom macros after each pass.
  1695.   SetFontSizes(10);
  1696.   wxNode *node = CustomMacroList.First();
  1697.   while (node)
  1698.   {
  1699.     CustomMacro *macro = (CustomMacro *)node->Data();
  1700.     delete macro;
  1701.     delete node;
  1702.     node = CustomMacroList.First();
  1703.   }
  1704. */
  1705.   TexReferences.BeginFind();
  1706.   wxNode *node = TexReferences.Next();
  1707.   while (node)
  1708.   {
  1709.     TexRef *ref = (TexRef *)node->Data();
  1710.     delete ref;
  1711.     node = TexReferences.Next();
  1712.   }
  1713.   TexReferences.Clear();
  1714.   
  1715.   node = BibList.First();
  1716.   while (node)
  1717.   {
  1718.     BibEntry *entry = (BibEntry *)node->Data();
  1719.     delete entry;
  1720.     delete node;
  1721.     node = BibList.First();
  1722.   }
  1723.   CitationList.Clear();
  1724.   ResetTopicCounter();
  1725. }
  1726.  
  1727. // There is likely to be one set of macros used by all utilities.
  1728. void DefineDefaultMacros(void)
  1729. {
  1730.   // Put names which subsume other names at the TOP
  1731.   // so they get recognized first
  1732.  
  1733.   AddMacroDef(ltACCENT_GRAVE,     "`", 1);
  1734.   AddMacroDef(ltACCENT_ACUTE,     "'", 1);
  1735.   AddMacroDef(ltACCENT_CARET,     "^", 1);
  1736.   AddMacroDef(ltACCENT_UMLAUT,    "\"", 1);
  1737.   AddMacroDef(ltACCENT_TILDE,     "~", 1);
  1738.   AddMacroDef(ltACCENT_DOT,       ".", 1);
  1739.   AddMacroDef(ltACCENT_CADILLA,   "c", 1);
  1740.  
  1741.   AddMacroDef(ltABSTRACT,         "abstract", 1);
  1742.   AddMacroDef(ltADDCONTENTSLINE,  "addcontentsline", 3);
  1743.   AddMacroDef(ltADDTOCOUNTER,     "addtocounter", 2);
  1744.   AddMacroDef(ltALEPH,            "aleph", 0);
  1745.   AddMacroDef(ltALPHA,            "alpha", 0);
  1746.   AddMacroDef(ltALPH1,            "alph", 1);
  1747.   AddMacroDef(ltALPH2,            "Alph", 1);
  1748.   AddMacroDef(ltANGLE,            "angle", 0);
  1749.   AddMacroDef(ltAPPENDIX,         "appendix", 0);
  1750.   AddMacroDef(ltAPPROX,           "approx", 0);
  1751.   AddMacroDef(ltARABIC,           "arabic", 1);
  1752.   AddMacroDef(ltARRAY,            "array", 1);
  1753.   AddMacroDef(ltAST,              "ast", 0);
  1754.   AddMacroDef(ltASYMP,            "asymp", 0);
  1755.   AddMacroDef(ltAUTHOR,           "author", 1);
  1756.  
  1757.   AddMacroDef(ltBACKSLASH,        "backslash", 0);
  1758.   AddMacroDef(ltBASELINESKIP,     "baselineskip", 1);
  1759.   AddMacroDef(ltBCOL,             "bcol", 2);
  1760.   AddMacroDef(ltBETA,             "beta", 0);
  1761.   AddMacroDef(ltBF,               "bf", 1);
  1762.   AddMacroDef(ltBIBITEM,          "bibitem", 2);  // For convenience, bibitem has 2 args: label and item.
  1763.                               // The Latex syntax permits writing as 2 args.
  1764.   AddMacroDef(ltBIBLIOGRAPHYSTYLE,    "bibliographystyle", 1);
  1765.   AddMacroDef(ltBIBLIOGRAPHY,     "bibliography", 1);
  1766.   AddMacroDef(ltBIGTRIANGLEDOWN,  "bigtriangledown", 0);
  1767.   AddMacroDef(ltBOT,              "bot", 0);
  1768.   AddMacroDef(ltBOXIT,            "boxit", 1);
  1769.   AddMacroDef(ltBOX,              "box", 0);
  1770.   AddMacroDef(ltBULLET,           "bullet", 0);
  1771.  
  1772.   AddMacroDef(ltCAPTIONSTAR,      "caption*", 1);
  1773.   AddMacroDef(ltCAPTION,          "caption", 1);
  1774.   AddMacroDef(ltCAP,              "cap", 0);
  1775.   AddMacroDef(ltCDOTS,            "cdots", 0);
  1776.   AddMacroDef(ltCDOT,             "cdot", 0);
  1777.   AddMacroDef(ltCENTERLINE,       "centerline", 1);
  1778.   AddMacroDef(ltCENTERING,        "centering", 0);
  1779.   AddMacroDef(ltCENTER,           "center", 1);
  1780.   AddMacroDef(ltCEXTRACT,         "cextract", 0);
  1781.   AddMacroDef(ltCHAPTERHEADING,   "chapterheading", 1);
  1782.   AddMacroDef(ltCHAPTERSTAR,      "chapter*", 1);
  1783.   AddMacroDef(ltCHAPTER,          "chapter", 1);
  1784.   AddMacroDef(ltCHI,              "chi", 0);
  1785.   AddMacroDef(ltCINSERT,          "cinsert", 0);
  1786.   AddMacroDef(ltCIRC,             "circ", 0);
  1787.   AddMacroDef(ltCITE,             "cite", 1);
  1788.   AddMacroDef(ltCLASS,            "class", 1);
  1789.   AddMacroDef(ltCLEARDOUBLEPAGE,  "cleardoublepage", 0);
  1790.   AddMacroDef(ltCLEARPAGE,        "clearpage", 0);
  1791.   AddMacroDef(ltCLINE,            "cline", 1);
  1792.   AddMacroDef(ltCLIPSFUNC,        "clipsfunc", 3);
  1793.   AddMacroDef(ltCLUBSUIT,         "clubsuit", 0);
  1794.   AddMacroDef(ltCOLUMNSEP,        "columnsep", 1);
  1795.   AddMacroDef(ltCOMMENT,          "comment", 1, TRUE);
  1796.   AddMacroDef(ltCONG,             "cong", 0);
  1797.   AddMacroDef(ltCOPYRIGHT,        "copyright", 0);
  1798.   AddMacroDef(ltCPARAM,           "cparam", 2);
  1799.   AddMacroDef(ltCHEAD,            "chead", 1);
  1800.   AddMacroDef(ltCFOOT,            "cfoot", 1);
  1801.   AddMacroDef(ltCUP,              "cup", 0);
  1802.  
  1803.   AddMacroDef(ltDASHV,            "dashv", 0);
  1804.   AddMacroDef(ltDATE,             "date", 1);
  1805.   AddMacroDef(ltDELTA,            "delta", 0);
  1806.   AddMacroDef(ltCAP_DELTA,        "Delta", 0);
  1807.   AddMacroDef(ltDEFINECOLOUR,     "definecolour", 4);
  1808.   AddMacroDef(ltDEFINECOLOR,      "definecolor", 4);
  1809.   AddMacroDef(ltDESCRIPTION,      "description", 1);
  1810.   AddMacroDef(ltDESTRUCT,         "destruct", 1);
  1811.   AddMacroDef(ltDIAMOND2,         "diamond2", 0);
  1812.   AddMacroDef(ltDIAMOND,          "diamond", 0);
  1813.   AddMacroDef(ltDIV,              "div", 0);
  1814.   AddMacroDef(ltDOCUMENTSTYLE,    "documentstyle", 1);
  1815.   AddMacroDef(ltDOCUMENT,         "document", 1);
  1816.   AddMacroDef(ltDOUBLESPACE,      "doublespace", 1);
  1817.   AddMacroDef(ltDOTEQ,            "doteq", 0);
  1818.   AddMacroDef(ltDOWNARROW,        "downarrow", 0);
  1819.   AddMacroDef(ltDOWNARROW2,       "Downarrow", 0);
  1820.  
  1821.   AddMacroDef(ltEM,               "em", 1);
  1822.   AddMacroDef(ltEMPTYSET,         "emptyset", 0);
  1823.   AddMacroDef(ltENUMERATE,        "enumerate", 1);
  1824.   AddMacroDef(ltEPSILON,          "epsilon", 0);
  1825.   AddMacroDef(ltEQUATION,         "equation", 1);
  1826.   AddMacroDef(ltEQUIV,            "equiv", 0);
  1827.   AddMacroDef(ltETA,              "eta", 0);
  1828.   AddMacroDef(ltEVENSIDEMARGIN,   "evensidemargin", 1);
  1829.   AddMacroDef(ltEXISTS,           "exists", 0);
  1830.  
  1831.   AddMacroDef(ltFBOX,             "fbox", 1);
  1832.   AddMacroDef(ltFCOL,             "fcol", 2);
  1833.   AddMacroDef(ltFIGURE,           "figure", 1);
  1834.   AddMacroDef(ltFIGURESTAR,       "figure*", 1);
  1835.   AddMacroDef(ltFLUSHLEFT,        "flushleft", 1);
  1836.   AddMacroDef(ltFLUSHRIGHT,       "flushright", 1);
  1837.   AddMacroDef(ltFOOTHEIGHT,       "footheight", 1);
  1838.   AddMacroDef(ltFOOTNOTEPOPUP,    "footnotepopup", 2);
  1839.   AddMacroDef(ltFOOTNOTE,         "footnote", 1);
  1840.   AddMacroDef(ltFOOTSKIP,         "footskip", 1);
  1841.   AddMacroDef(ltFORALL,           "forall", 0);
  1842.   AddMacroDef(ltFRAMEBOX,         "framebox", 1);
  1843.   AddMacroDef(ltFROWN,            "frown", 0);
  1844.   AddMacroDef(ltFUNCTIONSECTION,  "functionsection", 1);
  1845.   AddMacroDef(ltFUNC,             "func", 3);
  1846.   AddMacroDef(ltFOOTNOTESIZE,     "footnotesize", 1);
  1847.   AddMacroDef(ltFANCYPLAIN,       "fancyplain", 2);
  1848.  
  1849.   AddMacroDef(ltGAMMA,            "gamma", 0);
  1850.   AddMacroDef(ltCAP_GAMMA,        "Gamma", 0);
  1851.   AddMacroDef(ltGEQ,              "geq", 0);
  1852.   AddMacroDef(ltGE,               "ge", 0);
  1853.   AddMacroDef(ltGG,               "gg", 0);
  1854.   AddMacroDef(ltGLOSSARY,         "glossary", 1);
  1855.   AddMacroDef(ltGLOSS,            "gloss", 1);
  1856.  
  1857.   AddMacroDef(ltHEADHEIGHT,       "headheight", 1);
  1858.   AddMacroDef(ltHEARTSUIT,        "heartsuit", 0);
  1859.   AddMacroDef(ltHELPGLOSSARY,     "helpglossary", 1);
  1860.   AddMacroDef(ltHELPIGNORE,       "helpignore", 1, TRUE);
  1861.   AddMacroDef(ltHELPONLY,         "helponly", 1);
  1862.   AddMacroDef(ltHELPINPUT,        "helpinput", 1);
  1863.   AddMacroDef(ltHELPFONTFAMILY,   "helpfontfamily", 1);
  1864.   AddMacroDef(ltHELPFONTSIZE,     "helpfontsize", 1);
  1865.   AddMacroDef(ltHELPREFN,         "helprefn", 2);
  1866.   AddMacroDef(ltHELPREF,          "helpref", 2);
  1867.   AddMacroDef(ltHFILL,            "hfill", 0);
  1868.   AddMacroDef(ltHLINE,            "hline", 0);
  1869.   AddMacroDef(ltHRULE,            "hrule", 0);
  1870.   AddMacroDef(ltHSPACESTAR,       "hspace*", 1);
  1871.   AddMacroDef(ltHSPACE,           "hspace", 1);
  1872.   AddMacroDef(ltHSKIPSTAR,        "hskip*", 1);
  1873.   AddMacroDef(ltHSKIP,            "hskip", 1);
  1874.   AddMacroDef(lthuge,             "huge", 1);
  1875.   AddMacroDef(ltHuge,             "Huge", 1);
  1876.   AddMacroDef(ltHUGE,             "HUGE", 1);
  1877.   AddMacroDef(ltHTMLIGNORE,       "htmlignore", 1);
  1878.   AddMacroDef(ltHTMLONLY,         "htmlonly", 1);
  1879.  
  1880.   AddMacroDef(ltIM,               "im", 0);
  1881.   AddMacroDef(ltINCLUDEONLY,      "includeonly", 1);
  1882.   AddMacroDef(ltINCLUDE,          "include", 1);
  1883.   AddMacroDef(ltINDENTED,         "indented", 2);
  1884.   AddMacroDef(ltINDEX,            "index", 1);
  1885.   AddMacroDef(ltINPUT,            "input", 1);
  1886.   AddMacroDef(ltIOTA,             "iota", 0);
  1887.   AddMacroDef(ltITEMIZE,          "itemize", 1);
  1888.   AddMacroDef(ltITEM,             "item", 0);
  1889.   AddMacroDef(ltIMAGE,            "image", 2);
  1890.   AddMacroDef(ltIN,               "in", 0);
  1891.   AddMacroDef(ltINFTY,            "infty", 0);
  1892.   AddMacroDef(ltIT,               "it", 1);
  1893.   AddMacroDef(ltITEMSEP,          "itemsep", 1);
  1894.  
  1895.   AddMacroDef(ltKAPPA,            "kappa", 0);
  1896.   AddMacroDef(ltKILL,             "kill", 0);
  1897.  
  1898.   AddMacroDef(ltLABEL,            "label", 1);
  1899.   AddMacroDef(ltLAMBDA,           "lambda", 0);
  1900.   AddMacroDef(ltCAP_LAMBDA,       "Lambda", 0);
  1901.   AddMacroDef(ltlarge,            "large", 1);
  1902.   AddMacroDef(ltLarge,            "Large", 1);
  1903.   AddMacroDef(ltLARGE,            "LARGE", 1);
  1904.   AddMacroDef(ltLATEXIGNORE,      "latexignore", 1);
  1905.   AddMacroDef(ltLATEXONLY,        "latexonly", 1);
  1906.   AddMacroDef(ltLATEX,            "LaTeX", 0);
  1907.   AddMacroDef(ltLBOX,             "lbox", 1);
  1908.   AddMacroDef(ltLDOTS,            "ldots", 0);
  1909.   AddMacroDef(ltLEQ,              "leq", 0);
  1910.   AddMacroDef(ltLE,               "le", 0);
  1911.   AddMacroDef(ltLEFTARROW,        "leftarrow", 0);
  1912.   AddMacroDef(ltLEFTRIGHTARROW,   "leftrightarrow", 0);
  1913.   AddMacroDef(ltLEFTARROW2,       "Leftarrow", 0);
  1914.   AddMacroDef(ltLEFTRIGHTARROW2,  "Leftrightarrow", 0);
  1915.   AddMacroDef(ltLINEBREAK,        "linebreak", 0);
  1916.   AddMacroDef(ltLISTOFFIGURES,    "listoffigures", 0);
  1917.   AddMacroDef(ltLISTOFTABLES,     "listoftables", 0);
  1918.   AddMacroDef(ltLHEAD,            "lhead", 1);
  1919.   AddMacroDef(ltLFOOT,            "lfoot", 1);
  1920.   AddMacroDef(ltLL,               "ll", 0);
  1921.  
  1922.   AddMacroDef(ltMAKEGLOSSARY,     "makeglossary", 0);
  1923.   AddMacroDef(ltMAKEINDEX,        "makeindex", 0);
  1924.   AddMacroDef(ltMAKETITLE,        "maketitle", 0);
  1925.   AddMacroDef(ltMARKRIGHT,        "markright", 1);
  1926.   AddMacroDef(ltMARKBOTH,         "markboth", 2);
  1927.   AddMacroDef(ltMARGINPARWIDTH,   "marginparwidth", 1);
  1928.   AddMacroDef(ltMARGINPARSEP,     "marginparsep", 1);
  1929.   AddMacroDef(ltMARGINPARODD,     "marginparodd", 1);
  1930.   AddMacroDef(ltMARGINPAREVEN,    "marginpareven", 1);
  1931.   AddMacroDef(ltMARGINPAR,        "marginpar", 1);
  1932.   AddMacroDef(ltMBOX,             "mbox", 1);
  1933.   AddMacroDef(ltMEMBERSECTION,    "membersection", 1);
  1934.   AddMacroDef(ltMEMBER,           "member", 2);
  1935.   AddMacroDef(ltMID,              "mid", 0);
  1936.   AddMacroDef(ltMODELS,           "models", 0);
  1937.   AddMacroDef(ltMP,               "mp", 0);
  1938.   AddMacroDef(ltMULTICOLUMN,      "multicolumn", 3);
  1939.   AddMacroDef(ltMU,               "mu", 0);
  1940.  
  1941.   AddMacroDef(ltNABLA,            "nabla", 0);
  1942.   AddMacroDef(ltNEG,              "neg", 0);
  1943.   AddMacroDef(ltNEQ,              "neq", 0);
  1944.   AddMacroDef(ltNEWCOUNTER,       "newcounter", 1, FALSE, FORBID_ABSOLUTELY);
  1945.   AddMacroDef(ltNEWLINE,          "newline", 0);
  1946.   AddMacroDef(ltNEWPAGE,          "newpage", 0);
  1947.   AddMacroDef(ltNI,               "ni", 0);
  1948.   AddMacroDef(ltNOCITE,           "nocite", 1);
  1949.   AddMacroDef(ltNOINDENT,         "noindent", 0);
  1950.   AddMacroDef(ltNOLINEBREAK,      "nolinebreak", 0);
  1951.   AddMacroDef(ltNOPAGEBREAK,      "nopagebreak", 0);
  1952.   AddMacroDef(ltNORMALSIZE,       "normalsize", 1);
  1953.   AddMacroDef(ltNORMALBOX,        "normalbox", 1);
  1954.   AddMacroDef(ltNORMALBOXD,       "normalboxd", 1);
  1955.   AddMacroDef(ltNOTEQ,            "noteq", 0);
  1956.   AddMacroDef(ltNOTIN,            "notin", 0);
  1957.   AddMacroDef(ltNOTSUBSET,        "notsubset", 0);
  1958.   AddMacroDef(ltNU,               "nu", 0);
  1959.  
  1960.   AddMacroDef(ltODDSIDEMARGIN,    "oddsidemargin", 1);
  1961.   AddMacroDef(ltOMEGA,            "omega", 0);
  1962.   AddMacroDef(ltCAP_OMEGA,        "Omega", 0);
  1963.   AddMacroDef(ltONECOLUMN,        "onecolumn", 0);
  1964.   AddMacroDef(ltOPLUS,            "oplus", 0);
  1965.   AddMacroDef(ltOSLASH,           "oslash", 0);
  1966.   AddMacroDef(ltOTIMES,           "otimes", 0);
  1967.  
  1968.   AddMacroDef(ltPAGEBREAK,        "pagebreak", 0);
  1969.   AddMacroDef(ltPAGEREF,          "pageref", 1);
  1970.   AddMacroDef(ltPAGESTYLE,        "pagestyle", 1);
  1971.   AddMacroDef(ltPAGENUMBERING,    "pagenumbering", 1);
  1972.   AddMacroDef(ltPARAGRAPHSTAR,    "paragraph*", 1);
  1973.   AddMacroDef(ltPARAGRAPH,        "paragraph", 1);
  1974.   AddMacroDef(ltPARALLEL,         "parallel", 0);
  1975.   AddMacroDef(ltPARAM,            "param", 2);
  1976.   AddMacroDef(ltPARINDENT,        "parindent", 1);
  1977.   AddMacroDef(ltPARSKIP,          "parskip", 1);
  1978.   AddMacroDef(ltPARTIAL,          "partial", 0);
  1979.   AddMacroDef(ltPARTSTAR,         "part*", 1);
  1980.   AddMacroDef(ltPART,             "part", 1);
  1981.   AddMacroDef(ltPAR,              "par", 0);
  1982.   AddMacroDef(ltPERP,             "perp", 0);
  1983.   AddMacroDef(ltPHI,              "phi", 0);
  1984.   AddMacroDef(ltCAP_PHI,          "Phi", 0);
  1985.   AddMacroDef(ltPFUNC,            "pfunc", 3);
  1986.   AddMacroDef(ltPICTURE,          "picture", 1);
  1987.   AddMacroDef(ltPI,               "pi", 0);
  1988.   AddMacroDef(ltCAP_PI,           "Pi", 0);
  1989.   AddMacroDef(ltPM,               "pm", 0);
  1990.   AddMacroDef(ltPOPREF,           "popref", 2);
  1991.   AddMacroDef(ltPOUNDS,           "pounds", 0);
  1992.   AddMacroDef(ltPREC,             "prec", 0);
  1993.   AddMacroDef(ltPRECEQ,           "preceq", 0);
  1994.   AddMacroDef(ltPRINTINDEX,       "printindex", 0);
  1995.   AddMacroDef(ltPROPTO,           "propto", 0);
  1996.   AddMacroDef(ltPSBOXTO,          "psboxto", 1, FALSE, FORBID_ABSOLUTELY);
  1997.   AddMacroDef(ltPSBOX,            "psbox", 1, FALSE, FORBID_ABSOLUTELY);
  1998.   AddMacroDef(ltPSI,              "psi", 0);
  1999.   AddMacroDef(ltCAP_PSI,          "Psi", 0);
  2000.  
  2001.   AddMacroDef(ltQUOTE,            "quote", 1);
  2002.   AddMacroDef(ltQUOTATION,        "quotation", 1);
  2003.  
  2004.   AddMacroDef(ltRAGGEDBOTTOM,     "raggedbottom", 0);
  2005.   AddMacroDef(ltRAGGEDLEFT,       "raggedleft", 0);
  2006.   AddMacroDef(ltRAGGEDRIGHT,      "raggedright", 0);
  2007.   AddMacroDef(ltREF,              "ref", 1);
  2008.   AddMacroDef(ltRE,               "we", 0);
  2009.   AddMacroDef(ltRHO,              "rho", 0);
  2010.   AddMacroDef(ltRIGHTARROW,       "rightarrow", 0);
  2011.   AddMacroDef(ltRIGHTARROW2,      "rightarrow2", 0);
  2012.   AddMacroDef(ltRM,               "rm", 1);
  2013.   AddMacroDef(ltROMAN,            "roman", 1);
  2014.   AddMacroDef(ltROMAN2,           "Roman", 1);
  2015. //  AddMacroDef(lt"row", 1);
  2016.   AddMacroDef(ltRTFSP,            "rtfsp", 0);
  2017.   AddMacroDef(ltRTFIGNORE,        "rtfignore", 1);
  2018.   AddMacroDef(ltRTFONLY,          "rtfonly", 1);
  2019.   AddMacroDef(ltRULEDROW,         "ruledrow", 1);
  2020.   AddMacroDef(ltDRULED,           "druled", 1);
  2021.   AddMacroDef(ltRULE,             "rule", 2);
  2022.   AddMacroDef(ltRHEAD,            "rhead", 1);
  2023.   AddMacroDef(ltRFOOT,            "rfoot", 1);
  2024.   AddMacroDef(ltROW,              "row", 1);
  2025.  
  2026.   AddMacroDef(ltSC,               "sc", 1);
  2027.   AddMacroDef(ltSECTIONHEADING,   "sectionheading", 1);
  2028.   AddMacroDef(ltSECTIONSTAR,      "section*", 1);
  2029.   AddMacroDef(ltSECTION,          "section", 1);
  2030.   AddMacroDef(ltSETCOUNTER,       "setcounter", 2);
  2031.   AddMacroDef(ltSF,               "sf", 1);
  2032.   AddMacroDef(ltSHARP,            "sharp", 0);
  2033.   AddMacroDef(ltSHORTCITE,        "shortcite", 1);
  2034.   AddMacroDef(ltSIGMA,            "sigma", 0);
  2035.   AddMacroDef(ltCAP_SIGMA,        "Sigma", 0);
  2036.   AddMacroDef(ltSIM,              "sim", 0);
  2037.   AddMacroDef(ltSIMEQ,            "simeq", 0);
  2038.   AddMacroDef(ltSINGLESPACE,      "singlespace", 1);
  2039.   AddMacroDef(ltSIZEDBOX,         "sizedbox", 2);
  2040.   AddMacroDef(ltSIZEDBOXD,        "sizedboxd", 2);
  2041.   AddMacroDef(ltSLOPPYPAR,        "sloppypar", 1);
  2042.   AddMacroDef(ltSLOPPY,           "sloppy", 0);
  2043.   AddMacroDef(ltSL,               "sl", 1);
  2044.   AddMacroDef(ltSMALL,            "small", 1);
  2045.   AddMacroDef(ltSMILE,            "smile", 0);
  2046.   AddMacroDef(ltSS,               "ss", 0);
  2047.   AddMacroDef(ltSTAR,             "star", 0);
  2048.   AddMacroDef(ltSUBITEM,          "subitem", 0);
  2049.   AddMacroDef(ltSUBPARAGRAPHSTAR, "subparagraph*", 1);
  2050.   AddMacroDef(ltSUBPARAGRAPH,     "subparagraph", 1);
  2051.   AddMacroDef(ltSPECIAL,          "special", 1);
  2052.   AddMacroDef(ltSUBSECTIONSTAR,   "subsection*", 1);
  2053.   AddMacroDef(ltSUBSECTION,       "subsection", 1);
  2054.   AddMacroDef(ltSUBSETEQ,         "subseteq", 0);
  2055.   AddMacroDef(ltSUBSET,           "subset", 0);
  2056.   AddMacroDef(ltSUCC,             "succ", 0);
  2057.   AddMacroDef(ltSUCCEQ,           "succeq", 0);
  2058.   AddMacroDef(ltSUPSETEQ,         "supseteq", 0);
  2059.   AddMacroDef(ltSUPSET,           "supset", 0);
  2060.   AddMacroDef(ltSUBSUBSECTIONSTAR,"subsubsection*", 1);
  2061.   AddMacroDef(ltSUBSUBSECTION,    "subsubsection", 1);
  2062.   AddMacroDef(ltSUPERTABULAR,     "supertabular", 2, FALSE);
  2063.   AddMacroDef(ltSURD,             "surd", 0);
  2064.   AddMacroDef(ltSCRIPTSIZE,       "scriptsize", 1);
  2065.   AddMacroDef(ltSETHEADER,        "setheader", 6);
  2066.   AddMacroDef(ltSETFOOTER,        "setfooter", 6);
  2067.   AddMacroDef(ltSPADESUIT,        "spadesuit", 0);
  2068.  
  2069.   AddMacroDef(ltTABBING,          "tabbing", 2);
  2070.   AddMacroDef(ltTABLEOFCONTENTS,  "tableofcontents", 0);
  2071.   AddMacroDef(ltTABLE,            "table", 1);
  2072.   AddMacroDef(ltTABULAR,          "tabular", 2, FALSE);
  2073.   AddMacroDef(ltTAB,              "tab", 0);
  2074.   AddMacroDef(ltTAU,              "tau", 0);
  2075.   AddMacroDef(ltTEX,              "TeX", 0);
  2076.   AddMacroDef(ltTEXTWIDTH,        "textwidth", 1);
  2077.   AddMacroDef(ltTEXTHEIGHT,       "textheight", 1);
  2078.   AddMacroDef(ltTHEBIBLIOGRAPHY,  "thebibliography", 2);
  2079.   AddMacroDef(ltTHETA,            "theta", 0);
  2080.   AddMacroDef(ltTIMES,            "times", 0);
  2081.   AddMacroDef(ltCAP_THETA,        "Theta", 0);
  2082.   AddMacroDef(ltTITLEPAGE,        "titlepage", 1);
  2083.   AddMacroDef(ltTITLE,            "title", 1);
  2084.   AddMacroDef(ltTINY,             "tiny", 1);
  2085.   AddMacroDef(ltTODAY,            "today", 0);
  2086.   AddMacroDef(ltTOPMARGIN,        "topmargin", 1);
  2087.   AddMacroDef(ltTOPSKIP,          "topskip", 1);
  2088.   AddMacroDef(ltTRIANGLE,         "triangle", 0);
  2089.   AddMacroDef(ltTT,               "tt", 1);
  2090.   AddMacroDef(ltTYPEIN,           "typein", 1);
  2091.   AddMacroDef(ltTYPEOUT,          "typeout", 1);
  2092.   AddMacroDef(ltTWOCOLWIDTHA,     "twocolwidtha", 1);
  2093.   AddMacroDef(ltTWOCOLWIDTHB,     "twocolwidthb", 1);
  2094.   AddMacroDef(ltTWOCOLSPACING,    "twocolspacing", 1);
  2095.   AddMacroDef(ltTWOCOLITEMRULED,  "twocolitemruled", 2);
  2096.   AddMacroDef(ltTWOCOLITEM,       "twocolitem", 2);
  2097.   AddMacroDef(ltTWOCOLLIST,       "twocollist", 1);
  2098.   AddMacroDef(ltTWOCOLUMN,        "twocolumn", 0);
  2099.   AddMacroDef(ltTHEPAGE,          "thepage", 0);
  2100.   AddMacroDef(ltTHECHAPTER,       "thechapter", 0);
  2101.   AddMacroDef(ltTHESECTION,       "thesection", 0);
  2102.   AddMacroDef(ltTHISPAGESTYLE,    "thispagestyle", 1);
  2103.  
  2104.   AddMacroDef(ltUNDERLINE,        "underline", 1);
  2105.   AddMacroDef(ltUPSILON,          "upsilon", 0);
  2106.   AddMacroDef(ltCAP_UPSILON,      "Upsilon", 0);
  2107.   AddMacroDef(ltUPARROW,          "uparrow", 0);
  2108.   AddMacroDef(ltUPARROW2,         "Uparrow", 0);
  2109.   
  2110.   AddMacroDef(ltVAREPSILON,       "varepsilon", 0);
  2111.   AddMacroDef(ltVARPHI,           "varphi", 0);
  2112.   AddMacroDef(ltVARPI,            "varpi", 0);
  2113.   AddMacroDef(ltVARRHO,           "varrho", 0);
  2114.   AddMacroDef(ltVARSIGMA,         "varsigma", 0);
  2115.   AddMacroDef(ltVARTHETA,         "vartheta", 0);
  2116.   AddMacroDef(ltVDOTS,            "vdots", 0);
  2117.   AddMacroDef(ltVEE,              "vee", 0);
  2118.   AddMacroDef(ltVERBATIMINPUT,    "verbatiminput", 1);
  2119.   AddMacroDef(ltVERBATIM,         "verbatim", 1);
  2120.   AddMacroDef(ltVERBSTAR,         "verb*", 1);
  2121.   AddMacroDef(ltVERB,             "verb", 1);
  2122.   AddMacroDef(ltVERSE,            "verse", 1);
  2123.   AddMacroDef(ltVFILL,            "vfill", 0);
  2124.   AddMacroDef(ltVLINE,            "vline", 0);
  2125.   AddMacroDef(ltVOID,             "void", 0);
  2126.   AddMacroDef(ltVDASH,            "vdash", 0);
  2127.   AddMacroDef(ltVRULE,            "vrule", 0);
  2128.   AddMacroDef(ltVSPACESTAR,       "vspace*", 1);
  2129.   AddMacroDef(ltVSKIPSTAR,        "vskip*", 1);
  2130.   AddMacroDef(ltVSPACE,           "vspace", 1);
  2131.   AddMacroDef(ltVSKIP,            "vskip", 1);
  2132.  
  2133.   AddMacroDef(ltWEDGE,            "wedge", 0);
  2134.   AddMacroDef(ltWXCLIPS,          "wxclips", 0);
  2135.   AddMacroDef(ltWINHELPIGNORE,    "winhelpignore", 1);
  2136.   AddMacroDef(ltWINHELPONLY,      "winhelponly", 1);
  2137.   AddMacroDef(ltWP,               "wp", 0);
  2138.  
  2139.   AddMacroDef(ltXI,               "xi", 0);
  2140.   AddMacroDef(ltCAP_XI,           "Xi", 0);
  2141.   AddMacroDef(ltXLPIGNORE,        "xlpignore", 1);
  2142.   AddMacroDef(ltXLPONLY,          "xlponly", 1);
  2143.  
  2144.   AddMacroDef(ltZETA,             "zeta", 0);
  2145.  
  2146.   AddMacroDef(ltSPACE,            " ", 0);
  2147.   AddMacroDef(ltBACKSLASHCHAR,    "\\", 0);
  2148.   AddMacroDef(ltPIPE,             "|", 0);
  2149.   AddMacroDef(ltFORWARDSLASH,     "/", 0);
  2150.   AddMacroDef(ltUNDERSCORE,       "_", 0);
  2151.   AddMacroDef(ltAMPERSAND,        "&", 0);
  2152.   AddMacroDef(ltPERCENT,          "%", 0);
  2153.   AddMacroDef(ltDOLLAR,           "$", 0);
  2154.   AddMacroDef(ltHASH,             "#", 0);
  2155.   AddMacroDef(ltLPARENTH,         "(", 0);
  2156.   AddMacroDef(ltRPARENTH,         ")", 0);
  2157.   AddMacroDef(ltLBRACE,           "{", 0);
  2158.   AddMacroDef(ltRBRACE,           "}", 0);
  2159. //  AddMacroDef(ltEQUALS,           "=", 0);
  2160.   AddMacroDef(ltRANGLEBRA,        ">", 0);
  2161.   AddMacroDef(ltLANGLEBRA,        "<", 0);
  2162.   AddMacroDef(ltPLUS,             "+", 0);
  2163.   AddMacroDef(ltDASH,             "-", 0);
  2164.   AddMacroDef(ltAT_SYMBOL,        "@", 0);
  2165. //  AddMacroDef(ltSINGLEQUOTE,      "'", 0);
  2166. //  AddMacroDef(ltBACKQUOTE,        "`", 0);
  2167. }
  2168.  
  2169. /*
  2170.  * Default behaviour, should be called by client if can't match locally.
  2171.  *
  2172.  */
  2173.  
  2174. // Called on start/end of macro examination
  2175. void DefaultOnMacro(int macroId, int no_args, Bool start)
  2176. {
  2177.   switch (macroId)
  2178.   {
  2179.     // Default behaviour for abstract
  2180.     case ltABSTRACT:
  2181.     {
  2182.       if (start)
  2183.       {
  2184.         // Write the heading
  2185.         FakeCurrentSection("Abstract");
  2186.         OnMacro(ltPAR, 0, TRUE);
  2187.         OnMacro(ltPAR, 0, FALSE);
  2188.       }
  2189.       else
  2190.       {
  2191.         if (DocumentStyle == LATEX_ARTICLE)
  2192.           sectionNo --;
  2193.         else
  2194.           chapterNo --;
  2195.       }
  2196.       break;
  2197.     }
  2198.  
  2199.     // Default behaviour for glossary
  2200.     case ltHELPGLOSSARY:
  2201.     {
  2202.       if (start)
  2203.       {
  2204.         // Write the heading
  2205.         FakeCurrentSection(GlossaryNameString);
  2206.         OnMacro(ltPAR, 0, TRUE);
  2207.         OnMacro(ltPAR, 0, FALSE);
  2208.         if ((convertMode == TEX_RTF) && !winHelp)
  2209.         {
  2210.           OnMacro(ltPAR, 0, TRUE);
  2211.           OnMacro(ltPAR, 0, FALSE);
  2212.         }
  2213.       }
  2214.       break;
  2215.     }
  2216.     case ltSPECIALAMPERSAND:
  2217.       if (start)
  2218.         TexOutput("  ");
  2219.       break;
  2220.  
  2221.     case ltCINSERT:
  2222.       if (start)
  2223.         TexOutput("<<", TRUE);
  2224.       break;
  2225.     case ltCEXTRACT:
  2226.       if (start)
  2227.         TexOutput(">>", TRUE);
  2228.       break;
  2229.     case ltDESTRUCT:
  2230.       if (start)
  2231.         TexOutput("~", TRUE);
  2232.       break;
  2233.     case ltTILDE:
  2234.       if (start)
  2235.         TexOutput("~", TRUE);
  2236.       break;
  2237.     case ltSPECIALTILDE:
  2238.       if (start)
  2239.         TexOutput(" ", TRUE);
  2240.       break;
  2241.     case ltUNDERSCORE:
  2242.       if (start)
  2243.         TexOutput("_", TRUE);
  2244.       break;
  2245.     case ltHASH:
  2246.       if (start)
  2247.         TexOutput("#", TRUE);
  2248.       break;
  2249.     case ltAMPERSAND:
  2250.       if (start)
  2251.         TexOutput("&", TRUE);
  2252.       break;
  2253.     case ltSPACE:
  2254.       if (start)
  2255.         TexOutput(" ", TRUE);
  2256.       break;
  2257.     case ltPIPE:
  2258.       if (start)
  2259.         TexOutput("|", TRUE);
  2260.       break;
  2261.     case ltPERCENT:
  2262.       if (start)
  2263.         TexOutput("%", TRUE);
  2264.       break;
  2265.     case ltDOLLAR:
  2266.       if (start)
  2267.         TexOutput("$", TRUE);
  2268.       break;
  2269.     case ltLPARENTH:
  2270.       if (start)
  2271.         TexOutput("", TRUE);
  2272.       break;
  2273.     case ltRPARENTH:
  2274.       if (start)
  2275.         TexOutput("", TRUE);
  2276.       break;
  2277.     case ltLBRACE:
  2278.       if (start)
  2279.         TexOutput("{", TRUE);
  2280.       break;
  2281.     case ltRBRACE:
  2282.       if (start)
  2283.         TexOutput("}", TRUE);
  2284.       break;
  2285.     case ltCOPYRIGHT:
  2286.       if (start)
  2287.         TexOutput("(c)", TRUE);
  2288.       break;
  2289.     case ltBACKSLASH:
  2290.       if (start)    
  2291.         TexOutput("\\", TRUE);
  2292.       break;
  2293.     case ltLDOTS:
  2294.     case ltCDOTS:
  2295.       if (start)
  2296.         TexOutput("...", TRUE);
  2297.       break;
  2298.     case ltVDOTS:
  2299.       if (start)
  2300.         TexOutput("|", TRUE);
  2301.       break;
  2302.     case ltLATEX:
  2303.       if (start)
  2304.         TexOutput("LaTeX", TRUE);
  2305.       break;
  2306.     case ltTEX:
  2307.       if (start)
  2308.         TexOutput("TeX", TRUE);
  2309.       break;
  2310.     case ltPOUNDS:
  2311.       if (start)
  2312.         TexOutput("รบ", TRUE);
  2313.       break;
  2314.     case ltSPECIALDOUBLEDOLLAR:  // Interpret as center
  2315.       OnMacro(ltCENTER, no_args, start);
  2316.       break;
  2317.     case ltSL:
  2318.       OnMacro(ltIT, no_args, start);
  2319.       break;
  2320.     case ltPARAGRAPH:
  2321.     case ltPARAGRAPHSTAR:
  2322.     case ltSUBPARAGRAPH:
  2323.     case ltSUBPARAGRAPHSTAR:
  2324.       OnMacro(ltSUBSUBSECTION, no_args, start);
  2325.       break;
  2326.     case ltTODAY:
  2327.     {
  2328.       if (start)
  2329.       {
  2330. #ifdef wx_x
  2331.         long when;
  2332. #endif
  2333. #if (defined(wx_msw) || defined(wx_dos))
  2334.         time_t when;
  2335. #endif
  2336.         (void) time(&when);
  2337.         TexOutput(ctime(&when), TRUE);
  2338.       }
  2339.       break;
  2340.     }
  2341.     case ltNOINDENT:
  2342.       if (start)
  2343.         ParIndent = 0;
  2344.       break;
  2345.  
  2346.     // Symbols
  2347.     case ltALPHA:
  2348.       if (start) TexOutput("alpha");
  2349.       break;
  2350.     case ltBETA:
  2351.       if (start) TexOutput("beta");
  2352.       break;
  2353.     case ltGAMMA:
  2354.       if (start) TexOutput("gamma");
  2355.       break;
  2356.     case ltDELTA:
  2357.       if (start) TexOutput("delta");
  2358.       break;
  2359.     case ltEPSILON:
  2360.     case ltVAREPSILON:
  2361.       if (start) TexOutput("epsilon");
  2362.       break;
  2363.     case ltZETA:
  2364.       if (start) TexOutput("zeta");
  2365.       break;
  2366.     case ltETA:
  2367.       if (start) TexOutput("eta");
  2368.       break;
  2369.     case ltTHETA:
  2370.     case ltVARTHETA:
  2371.       if (start) TexOutput("theta");
  2372.       break;
  2373.     case ltIOTA:
  2374.       if (start) TexOutput("iota");
  2375.       break;
  2376.     case ltKAPPA:
  2377.       if (start) TexOutput("kappa");
  2378.       break;
  2379.     case ltLAMBDA:
  2380.       if (start) TexOutput("lambda");
  2381.       break;
  2382.     case ltMU:
  2383.       if (start) TexOutput("mu");
  2384.       break;
  2385.     case ltNU:
  2386.       if (start) TexOutput("nu");
  2387.       break;
  2388.     case ltXI:
  2389.       if (start) TexOutput("xi");
  2390.       break;
  2391.     case ltPI:
  2392.     case ltVARPI:
  2393.       if (start) TexOutput("pi");
  2394.       break;
  2395.     case ltRHO:
  2396.     case ltVARRHO:
  2397.       if (start) TexOutput("rho");
  2398.       break;
  2399.     case ltSIGMA:
  2400.     case ltVARSIGMA:
  2401.       if (start) TexOutput("sigma");
  2402.       break;
  2403.     case ltTAU:
  2404.       if (start) TexOutput("tau");
  2405.       break;
  2406.     case ltUPSILON:
  2407.       if (start) TexOutput("upsilon");
  2408.       break;
  2409.     case ltPHI:
  2410.     case ltVARPHI:
  2411.       if (start) TexOutput("phi");
  2412.       break;
  2413.     case ltCHI:
  2414.       if (start) TexOutput("chi");
  2415.       break;
  2416.     case ltPSI:
  2417.       if (start) TexOutput("psi");
  2418.       break;
  2419.     case ltOMEGA:
  2420.       if (start) TexOutput("omega");
  2421.       break;
  2422.     case ltCAP_GAMMA:
  2423.       if (start) TexOutput("GAMMA");
  2424.       break;
  2425.     case ltCAP_DELTA:
  2426.       if (start) TexOutput("DELTA");
  2427.       break;
  2428.     case ltCAP_THETA:
  2429.       if (start) TexOutput("THETA");
  2430.       break;
  2431.     case ltCAP_LAMBDA:
  2432.       if (start) TexOutput("LAMBDA");
  2433.       break;
  2434.     case ltCAP_XI:
  2435.       if (start) TexOutput("XI");
  2436.       break;
  2437.     case ltCAP_PI:
  2438.       if (start) TexOutput("PI");
  2439.       break;
  2440.     case ltCAP_SIGMA:
  2441.       if (start) TexOutput("SIGMA");
  2442.       break;
  2443.     case ltCAP_UPSILON:
  2444.       if (start) TexOutput("UPSILON");
  2445.       break;
  2446.     case ltCAP_PHI:
  2447.       if (start) TexOutput("PHI");
  2448.       break;
  2449.     case ltCAP_PSI:
  2450.       if (start) TexOutput("PSI");
  2451.       break;
  2452.     case ltCAP_OMEGA:
  2453.       if (start) TexOutput("OMEGA");
  2454.       break;
  2455.  
  2456.     // Binary operation symbols
  2457.     case ltLE:
  2458.     case ltLEQ:
  2459.       if (start) TexOutput("<=");
  2460.       break;
  2461.     case ltLL:
  2462.       if (start) TexOutput("<<");
  2463.       break;
  2464.     case ltSUBSET:
  2465.       if (start) TexOutput("SUBSET");
  2466.       break;
  2467.     case ltSUBSETEQ:
  2468.       if (start) TexOutput("SUBSETEQ");
  2469.       break;
  2470.     case ltIN:
  2471.       if (start) TexOutput("IN");
  2472.       break;
  2473.     case ltVDASH:
  2474.       if (start) TexOutput("VDASH");
  2475.       break;
  2476.     case ltMODELS:
  2477.       if (start) TexOutput("MODELS");
  2478.       break;
  2479.     case ltGE:
  2480.     case ltGEQ:
  2481.       if (start) TexOutput(">=");
  2482.       break;
  2483.     case ltGG:
  2484.       if (start) TexOutput(">>");
  2485.       break;
  2486.     case ltSUPSET:
  2487.       if (start) TexOutput("SUPSET");
  2488.       break;
  2489.     case ltSUPSETEQ:
  2490.       if (start) TexOutput("SUPSETEQ");
  2491.       break;
  2492.     case ltNI:
  2493.       if (start) TexOutput("NI");
  2494.       break;
  2495.     case ltDASHV:
  2496.       if (start) TexOutput("DASHV");
  2497.       break;
  2498.     case ltPERP:
  2499.       if (start) TexOutput("PERP");
  2500.       break;
  2501.     case ltNEQ:
  2502.       if (start) TexOutput("NEQ");
  2503.       break;
  2504.     case ltDOTEQ:
  2505.       if (start) TexOutput("DOTEQ");
  2506.       break;
  2507.     case ltAPPROX:
  2508.       if (start) TexOutput("APPROX");
  2509.       break;
  2510.     case ltCONG:
  2511.       if (start) TexOutput("CONG");
  2512.       break;
  2513.     case ltEQUIV:
  2514.       if (start) TexOutput("EQUIV");
  2515.       break;
  2516.     case ltPROPTO:
  2517.       if (start) TexOutput("PROPTO");
  2518.       break;
  2519.     case ltPREC:
  2520.       if (start) TexOutput("PREC");
  2521.       break;
  2522.     case ltPRECEQ:
  2523.       if (start) TexOutput("PRECEQ");
  2524.       break;
  2525.     case ltPARALLEL:
  2526.       if (start) TexOutput("|");
  2527.       break;
  2528.     case ltSIM:
  2529.       if (start) TexOutput("~");
  2530.       break;
  2531.     case ltSIMEQ:
  2532.       if (start) TexOutput("SIMEQ");
  2533.       break;
  2534.     case ltASYMP:
  2535.       if (start) TexOutput("ASYMP");
  2536.       break;
  2537.     case ltSMILE:
  2538.       if (start) TexOutput(":-)");
  2539.       break;
  2540.     case ltFROWN:
  2541.       if (start) TexOutput(":-(");
  2542.       break;
  2543.     case ltSUCC:
  2544.       if (start) TexOutput("SUCC");
  2545.       break;
  2546.     case ltSUCCEQ:
  2547.       if (start) TexOutput("SUCCEQ");
  2548.       break;
  2549.     case ltMID:
  2550.       if (start) TexOutput("|");
  2551.       break;
  2552.  
  2553.     // Negated relation symbols
  2554.     case ltNOTEQ:
  2555.       if (start) TexOutput("!=");
  2556.       break;
  2557.     case ltNOTIN:
  2558.       if (start) TexOutput("NOTIN");
  2559.       break;
  2560.     case ltNOTSUBSET:
  2561.       if (start) TexOutput("NOTSUBSET");
  2562.       break;
  2563.  
  2564.     // Arrows
  2565.     case ltLEFTARROW:
  2566.       if (start) TexOutput("<--");
  2567.       break;
  2568.     case ltLEFTARROW2:
  2569.       if (start) TexOutput("<==");
  2570.       break;
  2571.     case ltRIGHTARROW:
  2572.       if (start) TexOutput("-->");
  2573.       break;
  2574.     case ltRIGHTARROW2:
  2575.       if (start) TexOutput("==>");
  2576.       break;
  2577.     case ltLEFTRIGHTARROW:
  2578.       if (start) TexOutput("<-->");
  2579.       break;
  2580.     case ltLEFTRIGHTARROW2:
  2581.       if (start) TexOutput("<==>");
  2582.       break;
  2583.     case ltUPARROW:
  2584.       if (start) TexOutput("UPARROW");
  2585.       break;
  2586.     case ltUPARROW2:
  2587.       if (start) TexOutput("UPARROW2");
  2588.       break;
  2589.     case ltDOWNARROW:
  2590.       if (start) TexOutput("DOWNARROW");
  2591.       break;
  2592.     case ltDOWNARROW2:
  2593.       if (start) TexOutput("DOWNARROW2");
  2594.       break;
  2595.     // Miscellaneous symbols
  2596.     case ltALEPH:
  2597.       if (start) TexOutput("ALEPH");
  2598.       break;
  2599.     case ltWP:
  2600.       if (start) TexOutput("WP");
  2601.       break;
  2602.     case ltRE:
  2603.       if (start) TexOutput("RE");
  2604.       break;
  2605.     case ltIM:
  2606.       if (start) TexOutput("IM");
  2607.       break;
  2608.     case ltEMPTYSET:
  2609.       if (start) TexOutput("EMPTYSET");
  2610.       break;
  2611.     case ltNABLA:
  2612.       if (start) TexOutput("NABLA");
  2613.       break;
  2614.     case ltSURD:
  2615.       if (start) TexOutput("SURD");
  2616.       break;
  2617.     case ltPARTIAL:
  2618.       if (start) TexOutput("PARTIAL");
  2619.       break;
  2620.     case ltBOT:
  2621.       if (start) TexOutput("BOT");
  2622.       break;
  2623.     case ltFORALL:
  2624.       if (start) TexOutput("FORALL");
  2625.       break;
  2626.     case ltEXISTS:
  2627.       if (start) TexOutput("EXISTS");
  2628.       break;
  2629.     case ltNEG:
  2630.       if (start) TexOutput("NEG");
  2631.       break;
  2632.     case ltSHARP:
  2633.       if (start) TexOutput("SHARP");
  2634.       break;
  2635.     case ltANGLE:
  2636.       if (start) TexOutput("ANGLE");
  2637.       break;
  2638.     case ltTRIANGLE:
  2639.       if (start) TexOutput("TRIANGLE");
  2640.       break;
  2641.     case ltCLUBSUIT:
  2642.       if (start) TexOutput("CLUBSUIT");
  2643.       break;
  2644.     case ltDIAMONDSUIT:
  2645.       if (start) TexOutput("DIAMONDSUIT");
  2646.       break;
  2647.     case ltHEARTSUIT:
  2648.       if (start) TexOutput("HEARTSUIT");
  2649.       break;
  2650.     case ltSPADESUIT:
  2651.       if (start) TexOutput("SPADESUIT");
  2652.       break;
  2653.     case ltINFTY:
  2654.       if (start) TexOutput("INFTY");
  2655.       break;
  2656.     case ltPM:
  2657.       if (start) TexOutput("PM");
  2658.       break;
  2659.     case ltMP:
  2660.       if (start) TexOutput("MP");
  2661.       break;
  2662.     case ltTIMES:
  2663.       if (start) TexOutput("TIMES");
  2664.       break;
  2665.     case ltDIV:
  2666.       if (start) TexOutput("DIV");
  2667.       break;
  2668.     case ltCDOT:
  2669.       if (start) TexOutput("CDOT");
  2670.       break;
  2671.     case ltAST:
  2672.       if (start) TexOutput("AST");
  2673.       break;
  2674.     case ltSTAR:
  2675.       if (start) TexOutput("STAR");
  2676.       break;
  2677.     case ltCAP:
  2678.       if (start) TexOutput("CAP");
  2679.       break;
  2680.     case ltCUP:
  2681.       if (start) TexOutput("CUP");
  2682.       break;
  2683.     case ltVEE:
  2684.       if (start) TexOutput("VEE");
  2685.       break;
  2686.     case ltWEDGE:
  2687.       if (start) TexOutput("WEDGE");
  2688.       break;
  2689.     case ltCIRC:
  2690.       if (start) TexOutput("CIRC");
  2691.       break;
  2692.     case ltBULLET:
  2693.       if (start) TexOutput("BULLET");
  2694.       break;
  2695.     case ltDIAMOND:
  2696.       if (start) TexOutput("DIAMOND");
  2697.       break;
  2698.     case ltOSLASH:
  2699.       if (start) TexOutput("OSLASH");
  2700.       break;
  2701.     case ltBOX:
  2702.       if (start) TexOutput("BOX");
  2703.       break;
  2704.     case ltDIAMOND2:
  2705.       if (start) TexOutput("DIAMOND2");
  2706.       break;
  2707.     case ltBIGTRIANGLEDOWN:
  2708.       if (start) TexOutput("BIGTRIANGLEDOWN");
  2709.       break;
  2710.     case ltOPLUS:
  2711.       if (start) TexOutput("OPLUS");
  2712.       break;
  2713.     case ltOTIMES:
  2714.       if (start) TexOutput("OTIMES");
  2715.       break;
  2716.     case ltSS:
  2717.       if (start) TexOutput("s");
  2718.       break;
  2719.     default:
  2720.       break;
  2721.   }
  2722. }
  2723.  
  2724. // Called on start/end of argument examination
  2725. Bool DefaultOnArgument(int macroId, int arg_no, Bool start)
  2726. {
  2727.   switch (macroId)
  2728.   {
  2729.     case ltREF:
  2730.     {
  2731.     if (arg_no == 1 && start)
  2732.     {
  2733.       char *refName = GetArgData();
  2734.       if (refName)
  2735.       {
  2736.         TexRef *texRef = FindReference(refName);
  2737.         if (texRef)
  2738.         {
  2739.           // Must strip the 'section' or 'chapter' or 'figure' text
  2740.           // from a normal 'ref' reference
  2741.           char buf[150];
  2742.           strcpy(buf, texRef->sectionNumber);
  2743.           int len = strlen(buf);
  2744.           int i = 0;
  2745.           if (strcmp(buf, "??") != 0)
  2746.           {
  2747.             while (i < len)
  2748.             {
  2749.               if (buf[i] == ' ')
  2750.               {
  2751.                 i ++;
  2752.                 break;
  2753.               }
  2754.               else i ++;
  2755.             }
  2756.           }
  2757.           TexOutput(texRef->sectionNumber + i, TRUE);
  2758.         }
  2759.         else
  2760.         {
  2761.           char buf[300];
  2762.           TexOutput("??", TRUE);
  2763.           sprintf(buf, "Warning: unresolved reference %s.", refName); 
  2764.           OnInform(buf);
  2765.         }
  2766.       }
  2767.       else TexOutput("??", TRUE);
  2768.       return FALSE;
  2769.     }
  2770.     break;
  2771.     }
  2772.     case ltLABEL:
  2773.     {
  2774.       return FALSE;
  2775.       break;
  2776.     }
  2777.     case ltAUTHOR:
  2778.     {
  2779.       if (start && (arg_no == 1))
  2780.         DocumentAuthor = GetArgChunk();
  2781.       return FALSE;
  2782.       break;
  2783.     }
  2784.     case ltDATE:
  2785.     {
  2786.       if (start && (arg_no == 1))
  2787.         DocumentDate = GetArgChunk();
  2788.       return FALSE;
  2789.       break;
  2790.     }
  2791.     case ltTITLE:
  2792.     {
  2793.       if (start && (arg_no == 1))
  2794.         DocumentTitle = GetArgChunk();
  2795.       return FALSE;
  2796.       break;
  2797.     }
  2798.   case ltDOCUMENTSTYLE:
  2799.   {
  2800.     if (start && !IsArgOptional())
  2801.     {
  2802.       DocumentStyleString = copystring(GetArgData());
  2803.       if (strncmp(DocumentStyleString, "art", 3) == 0)
  2804.         DocumentStyle = LATEX_ARTICLE;
  2805.       else if (strncmp(DocumentStyleString, "rep", 3) == 0)
  2806.         DocumentStyle = LATEX_REPORT;
  2807.       else if (strncmp(DocumentStyleString, "book", 4) == 0 ||
  2808.                strncmp(DocumentStyleString, "thesis", 6) == 0)
  2809.         DocumentStyle = LATEX_BOOK;
  2810.       else if (strncmp(DocumentStyleString, "letter", 6) == 0)
  2811.         DocumentStyle = LATEX_LETTER;
  2812.       else if (strncmp(DocumentStyleString, "slides", 6) == 0)
  2813.         DocumentStyle = LATEX_SLIDES;
  2814.         
  2815.       if (StringMatch("10", DocumentStyleString))
  2816.         SetFontSizes(10);
  2817.       else if (StringMatch("11", DocumentStyleString))
  2818.         SetFontSizes(11);
  2819.       else if (StringMatch("12", DocumentStyleString))
  2820.         SetFontSizes(12);
  2821.  
  2822.       OnMacro(ltHELPFONTSIZE, 1, TRUE);
  2823.       sprintf(currentArgData, "%d", normalFont);
  2824.       haveArgData = TRUE;
  2825.       OnArgument(ltHELPFONTSIZE, 1, TRUE);
  2826.       OnArgument(ltHELPFONTSIZE, 1, FALSE);
  2827.       haveArgData = FALSE;
  2828.       OnMacro(ltHELPFONTSIZE, 1, FALSE);
  2829.     }
  2830.     else if (start && IsArgOptional())
  2831.     {
  2832.       MinorDocumentStyleString = copystring(GetArgData());
  2833.  
  2834.       if (StringMatch("10", MinorDocumentStyleString))
  2835.         SetFontSizes(10);
  2836.       else if (StringMatch("11", MinorDocumentStyleString))
  2837.         SetFontSizes(11);
  2838.       else if (StringMatch("12", MinorDocumentStyleString))
  2839.         SetFontSizes(12);
  2840.     }
  2841.     return FALSE;
  2842.     break;
  2843.   }
  2844.   case ltBIBLIOGRAPHYSTYLE:
  2845.   {
  2846.     if (start && !IsArgOptional())
  2847.       BibliographyStyleString = copystring(GetArgData());
  2848.     return FALSE;
  2849.     break;
  2850.   }
  2851.   case ltPAGESTYLE:
  2852.   {
  2853.     if (start && !IsArgOptional())
  2854.     {
  2855.       if (PageStyle) delete[] PageStyle;
  2856.       PageStyle = copystring(GetArgData());
  2857.     }
  2858.     return FALSE;
  2859.     break;
  2860.   }
  2861. /*
  2862.   case ltLHEAD:
  2863.   {
  2864.     if (start && !IsArgOptional())
  2865.       LeftHeader = GetArgChunk();
  2866.     return FALSE;
  2867.     break;
  2868.   }
  2869.   case ltLFOOT:
  2870.   {
  2871.     if (start && !IsArgOptional())
  2872.       LeftFooter = GetArgChunk();
  2873.     return FALSE;
  2874.     break;
  2875.   }
  2876.   case ltCHEAD:
  2877.   {
  2878.     if (start && !IsArgOptional())
  2879.       CentreHeader = GetArgChunk();
  2880.     return FALSE;
  2881.     break;
  2882.   }
  2883.   case ltCFOOT:
  2884.   {
  2885.     if (start && !IsArgOptional())
  2886.       CentreFooter = GetArgChunk();
  2887.     return FALSE;
  2888.     break;
  2889.   }
  2890.   case ltRHEAD:
  2891.   {
  2892.     if (start && !IsArgOptional())
  2893.       RightHeader = GetArgChunk();
  2894.     return FALSE;
  2895.     break;
  2896.   }
  2897.   case ltRFOOT:
  2898.   {
  2899.     if (start && !IsArgOptional())
  2900.       RightFooter = GetArgChunk();
  2901.     return FALSE;
  2902.     break;
  2903.   }
  2904. */
  2905.   case ltCITE:
  2906.   case ltSHORTCITE:
  2907.   {
  2908.     if (start && !IsArgOptional())
  2909.     {
  2910.       char *citeKeys = GetArgData();
  2911.       int pos = 0;
  2912.       char *citeKey = ParseMultifieldString(citeKeys, &pos);
  2913.       while (citeKey)
  2914.       {
  2915.         AddCitation(citeKey);
  2916.         TexRef *ref = FindReference(citeKey);
  2917.         if (ref)
  2918.         {
  2919.           TexOutput(ref->sectionNumber, TRUE);
  2920.           if (strcmp(ref->sectionNumber, "??") == 0)
  2921.           {
  2922.             char buf[300];
  2923.             sprintf(buf, "Warning: unresolved citation %s.", citeKey);
  2924.             OnInform(buf);
  2925.           }
  2926.         }
  2927.         citeKey = ParseMultifieldString(citeKeys, &pos);
  2928.         if (citeKey)
  2929.         {
  2930.           TexOutput(", ", TRUE);
  2931.         }
  2932.       }
  2933.       return FALSE;
  2934.     }
  2935.     break;
  2936.   }
  2937.   case ltNOCITE:
  2938.   {
  2939.     if (start && !IsArgOptional())
  2940.     {
  2941.       char *citeKey = GetArgData();
  2942.       AddCitation(citeKey);
  2943.       return FALSE;
  2944.     }
  2945.     break;
  2946.   }
  2947.   case ltHELPFONTSIZE:
  2948.   {
  2949.     if (start)
  2950.     {
  2951.       char *data = GetArgData();
  2952.       if (strcmp(data, "10") == 0)
  2953.         SetFontSizes(10);
  2954.       else if (strcmp(data, "11") == 0)
  2955.         SetFontSizes(11);
  2956.       else if (strcmp(data, "12") == 0)
  2957.         SetFontSizes(12);
  2958.       return FALSE;
  2959.     }
  2960.     break;
  2961.   }
  2962.   case ltPAGEREF:
  2963.   {
  2964.     if (start)
  2965.     {
  2966.       TexOutput(" ??", TRUE);
  2967.       return FALSE;
  2968.     }
  2969.     break;
  2970.   }
  2971.   case ltPARSKIP:
  2972.   {
  2973.     if (start && arg_no == 1)
  2974.     {
  2975.       char *data = GetArgData();
  2976.       ParSkip = ParseUnitArgument(data);
  2977.       return FALSE;
  2978.     }
  2979.     break;
  2980.   }
  2981.   case ltPARINDENT:
  2982.   {
  2983.     if (start && arg_no == 1)
  2984.     {
  2985.       char *data = GetArgData();
  2986.       ParIndent = ParseUnitArgument(data);
  2987.       return FALSE;
  2988.     }
  2989.     break;
  2990.   }
  2991.   case ltSL:
  2992.   {
  2993.     return OnArgument(ltIT, arg_no, start);
  2994.     break;
  2995.   }
  2996.   case ltSPECIALDOUBLEDOLLAR:
  2997.   {
  2998.     return OnArgument(ltCENTER, arg_no, start);
  2999.     break;
  3000.   }
  3001.   case ltPARAGRAPH:
  3002.   case ltPARAGRAPHSTAR:
  3003.   case ltSUBPARAGRAPH:
  3004.   case ltSUBPARAGRAPHSTAR:
  3005.   {
  3006.     return OnArgument(ltSUBSUBSECTION, arg_no, start);
  3007.     break;
  3008.   }
  3009.   case ltTYPEOUT:
  3010.   {
  3011.     if (start)
  3012.       OnInform(GetArgData());
  3013.     break;
  3014.   }
  3015.   case ltFOOTNOTE:
  3016.   {
  3017.     if (start)
  3018.       TexOutput(" (", TRUE);
  3019.     else
  3020.       TexOutput(")", TRUE);
  3021.     break;
  3022.   }
  3023.   case ltBIBLIOGRAPHY:
  3024.   {
  3025.     if (start)
  3026.     {
  3027.       FILE *fd;
  3028.       char ch;
  3029.       char smallBuf[2];
  3030.       smallBuf[1] = 0;
  3031.       if (fd = fopen(TexBibName, "r"))
  3032.       {
  3033.         ch = getc(fd);
  3034.         smallBuf[0] = ch;
  3035.         while (ch != EOF)
  3036.         {
  3037.           TexOutput(smallBuf);
  3038.           ch = getc(fd);
  3039.           smallBuf[0] = ch;
  3040.         }
  3041.         fclose(fd);
  3042.       }
  3043.       else
  3044.       {
  3045.         OnInform("Run Tex2RTF again to include bibliography.");
  3046.       }
  3047.  
  3048.       // Read in the .bib file, resolve all known references, write out the RTF.
  3049.       char *allFiles = GetArgData();
  3050.       int pos = 0;
  3051.       char *bibFile = ParseMultifieldString(allFiles, &pos);
  3052.       while (bibFile)
  3053.       {
  3054.         char fileBuf[300];
  3055.         strcpy(fileBuf, bibFile);
  3056.         char *actualFile = TexPathList.FindValidPath(fileBuf);
  3057.         if (!actualFile)
  3058.         {
  3059.           strcat(fileBuf, ".bib");
  3060.           actualFile = TexPathList.FindValidPath(fileBuf);
  3061.         }
  3062.         if (actualFile)
  3063.         {
  3064.           if (!ReadBib(actualFile))
  3065.           {
  3066.             char buf[300];
  3067.             sprintf(buf, ".bib file %s not found or malformed", actualFile);
  3068.             OnError(buf);
  3069.           }
  3070.         }
  3071.         else
  3072.         {
  3073.           char buf[300];
  3074.           sprintf(buf, ".bib file %s not found", fileBuf);
  3075.           OnError(buf);
  3076.         }
  3077.         bibFile = ParseMultifieldString(allFiles, &pos);
  3078.       }
  3079.  
  3080.       ResolveBibReferences();
  3081.  
  3082.       // Write it a new bib section in the appropriate format.
  3083.       FILE *save1 = CurrentOutput1;
  3084.       FILE *save2 = CurrentOutput2;
  3085.       FILE *Biblio = fopen(TexTmpBibName, "w");
  3086.       SetCurrentOutput(Biblio);
  3087.       OutputBib();
  3088.       fclose(Biblio);
  3089.       if (FileExists(TexTmpBibName))
  3090.       {
  3091.         if (FileExists(TexBibName)) wxRemoveFile(TexBibName);
  3092.         wxRenameFile(TexTmpBibName, TexBibName);
  3093.       }
  3094.       SetCurrentOutputs(save1, save2);
  3095.       return FALSE;
  3096.     }
  3097.     break;
  3098.   }
  3099.   case ltMULTICOLUMN:
  3100.   {
  3101.     if (start && (arg_no == 3))
  3102.       return TRUE;
  3103.     else
  3104.       return FALSE;
  3105.     break;
  3106.   }
  3107.   case ltSC:
  3108.   {
  3109.     if (start && (arg_no == 1))
  3110.     {
  3111.       char *s = GetArgData();
  3112.       if (s)
  3113.       {
  3114.         char *s1 = copystring(s);
  3115.         for (int i = 0; i < (int)strlen(s); i++)
  3116.           s1[i] = toupper(s[i]);
  3117.         TexOutput(s1);
  3118.         delete[] s1;
  3119.         return FALSE;
  3120.       }
  3121.       else return TRUE;
  3122.  
  3123.     }
  3124.     return TRUE;
  3125.     break;
  3126.   }
  3127.   case ltPOPREF:  // Ignore second argument by default
  3128.   {
  3129.     if (start && (arg_no == 1))
  3130.       return TRUE;
  3131.     else
  3132.       return FALSE;
  3133.     break;
  3134.   }
  3135.   case ltTWOCOLUMN:
  3136.     return TRUE;
  3137.     break;
  3138.   case ltXLPIGNORE:
  3139.     return ((convertMode == TEX_XLP) ? FALSE : TRUE);
  3140.     break;
  3141.   case ltXLPONLY:
  3142.     return ((convertMode != TEX_XLP) ? FALSE : TRUE);
  3143.     break;
  3144.   case ltHTMLIGNORE:
  3145.     return ((convertMode == TEX_HTML) ? FALSE : TRUE);
  3146.     break;
  3147.   case ltHTMLONLY:
  3148.     return ((convertMode != TEX_HTML) ? FALSE : TRUE);
  3149.     break;
  3150.   case ltRTFIGNORE:
  3151.     return (((convertMode == TEX_RTF) && !winHelp) ? FALSE : TRUE);
  3152.     break;
  3153.   case ltRTFONLY:
  3154.     return (!((convertMode == TEX_RTF) && !winHelp) ? FALSE : TRUE);
  3155.     break;
  3156.   case ltWINHELPIGNORE:
  3157.     return (winHelp ? FALSE : TRUE);
  3158.     break;
  3159.   case ltWINHELPONLY:
  3160.     return (!winHelp ? FALSE : TRUE);
  3161.     break;
  3162.   case ltLATEXIGNORE:
  3163.     return TRUE;
  3164.     break;
  3165.   case ltLATEXONLY:
  3166.     return FALSE;
  3167.     break;
  3168.   case ltCLINE:
  3169.   case ltARABIC:
  3170.   case ltALPH1:
  3171.   case ltALPH2:
  3172.   case ltROMAN:
  3173.   case ltROMAN2:
  3174.   case ltSETCOUNTER:
  3175.   case ltADDTOCOUNTER:
  3176.   case ltADDCONTENTSLINE:
  3177.   case ltNEWCOUNTER:
  3178.   case ltTEXTWIDTH:
  3179.   case ltTEXTHEIGHT:
  3180.   case ltBASELINESKIP:
  3181.   case ltVSPACESTAR:
  3182.   case ltHSPACESTAR:
  3183.   case ltVSPACE:
  3184.   case ltHSPACE:
  3185.   case ltVSKIPSTAR:
  3186.   case ltHSKIPSTAR:
  3187.   case ltVSKIP:
  3188.   case ltHSKIP:
  3189.   case ltPAGENUMBERING:
  3190.   case ltTHEPAGE:
  3191.   case ltTHECHAPTER:
  3192.   case ltTHESECTION:
  3193.   case ltITEMSEP:
  3194.   case ltFANCYPLAIN:
  3195.   case ltCHEAD:
  3196.   case ltRHEAD:
  3197.   case ltLHEAD:
  3198.   case ltCFOOT:
  3199.   case ltRFOOT:
  3200.   case ltLFOOT:
  3201.   case ltTHISPAGESTYLE:
  3202.   case ltMARKRIGHT:
  3203.   case ltMARKBOTH:
  3204.   case ltEVENSIDEMARGIN:
  3205.   case ltODDSIDEMARGIN:
  3206.   case ltMARGINPAR:
  3207.   case ltMARGINPARWIDTH:
  3208.   case ltMARGINPARSEP:
  3209.   case ltMARGINPAREVEN:
  3210.   case ltMARGINPARODD:
  3211.   case ltTWOCOLWIDTHA:
  3212.   case ltTWOCOLWIDTHB:
  3213.   case ltTWOCOLSPACING:
  3214.   case ltSETHEADER:
  3215.   case ltSETFOOTER:
  3216.   case ltINDEX:
  3217.   case ltITEM:
  3218.   case ltBCOL:
  3219.   case ltFCOL:
  3220.     return FALSE;
  3221.     break;
  3222.   case ltTABULAR:
  3223.   case ltSUPERTABULAR:
  3224.   {
  3225.     if (arg_no == 2)
  3226.       return TRUE;
  3227.     else return FALSE;
  3228.     break;
  3229.   }
  3230.   case ltINDENTED:
  3231.   {
  3232.     if (arg_no == 2) return TRUE;
  3233.     else return FALSE;
  3234.     break;
  3235.   }
  3236.   case ltSIZEDBOX:
  3237.   case ltSIZEDBOXD:
  3238.   {
  3239.     if (arg_no == 2) return TRUE;
  3240.     else return FALSE;
  3241.     break;
  3242.   }
  3243.   case ltDEFINECOLOUR:
  3244.   case ltDEFINECOLOR:
  3245.   {
  3246.     static int redVal = 0;
  3247.     static int greenVal = 0;
  3248.     static int blueVal = 0;
  3249.     static char *colourName = NULL;
  3250.     if (start)
  3251.     {
  3252.       switch (arg_no)
  3253.       {
  3254.         case 1:
  3255.         {
  3256.           if (colourName) delete[] colourName;
  3257.           colourName = copystring(GetArgData());
  3258.           break;
  3259.         }
  3260.         case 2:
  3261.         {
  3262.           redVal = atoi(GetArgData());
  3263.           break;
  3264.         }
  3265.         case 3:
  3266.         {
  3267.           greenVal = atoi(GetArgData());
  3268.           break;
  3269.         }
  3270.         case 4:
  3271.         {
  3272.           blueVal = atoi(GetArgData());
  3273.           AddColour(colourName, redVal, greenVal, blueVal);
  3274.           break;
  3275.         }
  3276.         default:
  3277.           break;
  3278.       }
  3279.     }
  3280.     return FALSE;
  3281.     break;
  3282.   }
  3283.   case ltFIGURE:
  3284.   case ltFIGURESTAR:
  3285.   case ltNORMALBOX:
  3286.   case ltNORMALBOXD:
  3287.   default:
  3288.   {
  3289.     if (IsArgOptional())
  3290.       return FALSE;
  3291.     else
  3292.       return TRUE;
  3293.     break;
  3294.   }
  3295.   }
  3296.   return TRUE;
  3297. }
  3298.  
  3299.